* [PATCH v3 0/3] Add interconnect debugfs client @ 2023-08-07 14:29 Mike Tipton 2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton ` (2 more replies) 0 siblings, 3 replies; 11+ messages in thread From: Mike Tipton @ 2023-08-07 14:29 UTC (permalink / raw) To: djakov, gregkh, rafael, corbet Cc: linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti, Mike Tipton This series introduces interconnect debugfs files that support voting for any path the framework supports. We've historically relied on an out-of-tree module for this, which used the old icc_get() that was recently removed in [0]. The old icc_get() took integer endpoint IDs, which made identifying paths in our old implementation non-intuitive. The logical node names typically don't change much chip-to-chip, but the raw integer IDs do. Take this opportunity to introduce an icc_get() that uses string names instead, which allows for a more intuitive and generic debugfs interface. We rely on this support for debug, test, and verification. Hopefully it'll be useful for other vendors as well. [0] commit 7dcdad6f32c9 ("interconnect: drop unused icc_get() interface") Changes in v3: - Use GFP_ATOMIC when allocating with the rcu lock held. Changes in v2: - Make icc_get() an internal interface. - RCU-protect src_node and dst_node. - Replace PLATFORM_DEVID_AUTO with PLATFORM_DEVID_NONE. - Remove unnecessary #include. - Add debugfs client documentation. Mike Tipton (3): debugfs: Add write support to debugfs_create_str() interconnect: Reintroduce icc_get() interconnect: Add debugfs test client Documentation/driver-api/interconnect.rst | 25 ++++ drivers/interconnect/Makefile | 2 +- drivers/interconnect/core.c | 66 +++++++++ drivers/interconnect/debugfs-client.c | 168 ++++++++++++++++++++++ drivers/interconnect/internal.h | 3 + fs/debugfs/file.c | 48 ++++++- 6 files changed, 309 insertions(+), 3 deletions(-) create mode 100644 drivers/interconnect/debugfs-client.c -- 2.17.1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() 2023-08-07 14:29 [PATCH v3 0/3] Add interconnect debugfs client Mike Tipton @ 2023-08-07 14:29 ` Mike Tipton 2023-08-11 7:46 ` Georgi Djakov 2023-08-12 10:40 ` Greg KH 2023-08-07 14:29 ` [PATCH v3 2/3] interconnect: Reintroduce icc_get() Mike Tipton 2023-08-07 14:29 ` [PATCH v3 3/3] interconnect: Add debugfs test client Mike Tipton 2 siblings, 2 replies; 11+ messages in thread From: Mike Tipton @ 2023-08-07 14:29 UTC (permalink / raw) To: djakov, gregkh, rafael, corbet Cc: linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti, Mike Tipton Currently, debugfs_create_str() only supports reading strings from debugfs. Add support for writing them as well. Based on original implementation by Peter Zijlstra [0]. Write support was present in the initial patch version, but dropped in v2 due to lack of users. We have a user now, so reintroduce it. [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/ Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com> --- fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index b7711888dd17..87b3753aa4b1 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str); static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - /* This is really only for read-only strings */ - return -EINVAL; + struct dentry *dentry = F_DENTRY(file); + char *old, *new = NULL; + int pos = *ppos; + int r; + + r = debugfs_file_get(dentry); + if (unlikely(r)) + return r; + + old = *(char **)file->private_data; + + /* only allow strict concatenation */ + r = -EINVAL; + if (pos && pos != strlen(old)) + goto error; + + r = -E2BIG; + if (pos + count + 1 > PAGE_SIZE) + goto error; + + r = -ENOMEM; + new = kmalloc(pos + count + 1, GFP_KERNEL); + if (!new) + goto error; + + if (pos) + memcpy(new, old, pos); + + r = -EFAULT; + if (copy_from_user(new + pos, user_buf, count)) + goto error; + + new[pos + count] = '\0'; + strim(new); + + rcu_assign_pointer(*(char **)file->private_data, new); + synchronize_rcu(); + kfree(old); + + debugfs_file_put(dentry); + return count; + +error: + kfree(new); + debugfs_file_put(dentry); + return r; } static const struct file_operations fops_str = { -- 2.17.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() 2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton @ 2023-08-11 7:46 ` Georgi Djakov 2023-08-12 10:36 ` Greg KH 2023-08-12 10:40 ` Greg KH 1 sibling, 1 reply; 11+ messages in thread From: Georgi Djakov @ 2023-08-11 7:46 UTC (permalink / raw) To: Mike Tipton, gregkh, rafael, corbet Cc: linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti On 7.08.23 17:29, Mike Tipton wrote: > Currently, debugfs_create_str() only supports reading strings from > debugfs. Add support for writing them as well. > > Based on original implementation by Peter Zijlstra [0]. Write support > was present in the initial patch version, but dropped in v2 due to lack > of users. We have a user now, so reintroduce it. > > [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/ > Hi Greg, Looks like the original code was reviewed two years ago (not sure if it counts). But in any case, i need an ack from you to apply this. There is no build dependency with the rest of the patches (but there is a functional one). It should be also fine if you apply it directly, if you prefer so? Thanks, Georgi > Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com> > --- > fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 46 insertions(+), 2 deletions(-) > > diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c > index b7711888dd17..87b3753aa4b1 100644 > --- a/fs/debugfs/file.c > +++ b/fs/debugfs/file.c > @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str); > static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf, > size_t count, loff_t *ppos) > { > - /* This is really only for read-only strings */ > - return -EINVAL; > + struct dentry *dentry = F_DENTRY(file); > + char *old, *new = NULL; > + int pos = *ppos; > + int r; > + > + r = debugfs_file_get(dentry); > + if (unlikely(r)) > + return r; > + > + old = *(char **)file->private_data; > + > + /* only allow strict concatenation */ > + r = -EINVAL; > + if (pos && pos != strlen(old)) > + goto error; > + > + r = -E2BIG; > + if (pos + count + 1 > PAGE_SIZE) > + goto error; > + > + r = -ENOMEM; > + new = kmalloc(pos + count + 1, GFP_KERNEL); > + if (!new) > + goto error; > + > + if (pos) > + memcpy(new, old, pos); > + > + r = -EFAULT; > + if (copy_from_user(new + pos, user_buf, count)) > + goto error; > + > + new[pos + count] = '\0'; > + strim(new); > + > + rcu_assign_pointer(*(char **)file->private_data, new); > + synchronize_rcu(); > + kfree(old); > + > + debugfs_file_put(dentry); > + return count; > + > +error: > + kfree(new); > + debugfs_file_put(dentry); > + return r; > } > > static const struct file_operations fops_str = { ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() 2023-08-11 7:46 ` Georgi Djakov @ 2023-08-12 10:36 ` Greg KH 2023-08-12 10:37 ` Greg KH 0 siblings, 1 reply; 11+ messages in thread From: Greg KH @ 2023-08-12 10:36 UTC (permalink / raw) To: Georgi Djakov Cc: Mike Tipton, rafael, corbet, linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti On Fri, Aug 11, 2023 at 10:46:34AM +0300, Georgi Djakov wrote: > On 7.08.23 17:29, Mike Tipton wrote: > > Currently, debugfs_create_str() only supports reading strings from > > debugfs. Add support for writing them as well. > > > > Based on original implementation by Peter Zijlstra [0]. Write support > > was present in the initial patch version, but dropped in v2 due to lack > > of users. We have a user now, so reintroduce it. > > > > [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/ > > > > Hi Greg, > > Looks like the original code was reviewed two years ago (not sure if it > counts). But in any case, i need an ack from you to apply this. > > There is no build dependency with the rest of the patches (but there is a > functional one). It should be also fine if you apply it directly, if you > prefer so? Feel free for this to go with the code that uses it: Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() 2023-08-12 10:36 ` Greg KH @ 2023-08-12 10:37 ` Greg KH 0 siblings, 0 replies; 11+ messages in thread From: Greg KH @ 2023-08-12 10:37 UTC (permalink / raw) To: Georgi Djakov Cc: Mike Tipton, rafael, corbet, linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti On Sat, Aug 12, 2023 at 12:36:12PM +0200, Greg KH wrote: > On Fri, Aug 11, 2023 at 10:46:34AM +0300, Georgi Djakov wrote: > > On 7.08.23 17:29, Mike Tipton wrote: > > > Currently, debugfs_create_str() only supports reading strings from > > > debugfs. Add support for writing them as well. > > > > > > Based on original implementation by Peter Zijlstra [0]. Write support > > > was present in the initial patch version, but dropped in v2 due to lack > > > of users. We have a user now, so reintroduce it. > > > > > > [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/ > > > > > > > Hi Greg, > > > > Looks like the original code was reviewed two years ago (not sure if it > > counts). But in any case, i need an ack from you to apply this. > > > > There is no build dependency with the rest of the patches (but there is a > > functional one). It should be also fine if you apply it directly, if you > > prefer so? > > Feel free for this to go with the code that uses it: > > Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Wait, no, this isn't ok, this ACK is now rescinded: NACKED-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() 2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton 2023-08-11 7:46 ` Georgi Djakov @ 2023-08-12 10:40 ` Greg KH 2023-08-12 13:25 ` Georgi Djakov 2023-08-18 10:05 ` Georgi Djakov 1 sibling, 2 replies; 11+ messages in thread From: Greg KH @ 2023-08-12 10:40 UTC (permalink / raw) To: Mike Tipton Cc: djakov, rafael, corbet, linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti On Mon, Aug 07, 2023 at 07:29:12AM -0700, Mike Tipton wrote: > Currently, debugfs_create_str() only supports reading strings from > debugfs. Add support for writing them as well. > > Based on original implementation by Peter Zijlstra [0]. Write support > was present in the initial patch version, but dropped in v2 due to lack > of users. We have a user now, so reintroduce it. > > [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/ > > Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com> > --- > fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 46 insertions(+), 2 deletions(-) > > diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c > index b7711888dd17..87b3753aa4b1 100644 > --- a/fs/debugfs/file.c > +++ b/fs/debugfs/file.c > @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str); > static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf, > size_t count, loff_t *ppos) > { > - /* This is really only for read-only strings */ > - return -EINVAL; > + struct dentry *dentry = F_DENTRY(file); > + char *old, *new = NULL; > + int pos = *ppos; > + int r; > + > + r = debugfs_file_get(dentry); > + if (unlikely(r)) > + return r; > + > + old = *(char **)file->private_data; > + > + /* only allow strict concatenation */ > + r = -EINVAL; > + if (pos && pos != strlen(old)) > + goto error; > + > + r = -E2BIG; > + if (pos + count + 1 > PAGE_SIZE) > + goto error; > + > + r = -ENOMEM; > + new = kmalloc(pos + count + 1, GFP_KERNEL); > + if (!new) > + goto error; > + > + if (pos) > + memcpy(new, old, pos); > + > + r = -EFAULT; > + if (copy_from_user(new + pos, user_buf, count)) > + goto error; > + > + new[pos + count] = '\0'; > + strim(new); > + > + rcu_assign_pointer(*(char **)file->private_data, new); > + synchronize_rcu(); > + kfree(old); > + > + debugfs_file_put(dentry); > + return count; > + > +error: > + kfree(new); > + debugfs_file_put(dentry); > + return r; > } So you just added write support for ALL debugfs files that use the string interface, what did you just allow to break? I recommend just using your own debugfs file function instead, as this could cause bad problems, right? Are you sure that all string calls can handle the variable be freed underneath it like this call will allow to happen? So I wouldn't recommend doing this, sorry. greg k-h ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() 2023-08-12 10:40 ` Greg KH @ 2023-08-12 13:25 ` Georgi Djakov 2023-08-18 10:05 ` Georgi Djakov 1 sibling, 0 replies; 11+ messages in thread From: Georgi Djakov @ 2023-08-12 13:25 UTC (permalink / raw) To: Greg KH, Mike Tipton Cc: rafael, corbet, linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti Hi Greg, Thanks for the comments! On 12.08.23 13:40, Greg KH wrote: > On Mon, Aug 07, 2023 at 07:29:12AM -0700, Mike Tipton wrote: >> Currently, debugfs_create_str() only supports reading strings from >> debugfs. Add support for writing them as well. >> >> Based on original implementation by Peter Zijlstra [0]. Write support >> was present in the initial patch version, but dropped in v2 due to lack >> of users. We have a user now, so reintroduce it. >> >> [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/ >> >> Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com> >> --- >> fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++-- >> 1 file changed, 46 insertions(+), 2 deletions(-) >> >> diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c >> index b7711888dd17..87b3753aa4b1 100644 >> --- a/fs/debugfs/file.c >> +++ b/fs/debugfs/file.c >> @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str); >> static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf, >> size_t count, loff_t *ppos) >> { >> - /* This is really only for read-only strings */ >> - return -EINVAL; >> + struct dentry *dentry = F_DENTRY(file); >> + char *old, *new = NULL; >> + int pos = *ppos; >> + int r; >> + >> + r = debugfs_file_get(dentry); >> + if (unlikely(r)) >> + return r; >> + >> + old = *(char **)file->private_data; >> + >> + /* only allow strict concatenation */ >> + r = -EINVAL; >> + if (pos && pos != strlen(old)) >> + goto error; >> + >> + r = -E2BIG; >> + if (pos + count + 1 > PAGE_SIZE) >> + goto error; >> + >> + r = -ENOMEM; >> + new = kmalloc(pos + count + 1, GFP_KERNEL); >> + if (!new) >> + goto error; >> + >> + if (pos) >> + memcpy(new, old, pos); >> + >> + r = -EFAULT; >> + if (copy_from_user(new + pos, user_buf, count)) >> + goto error; >> + >> + new[pos + count] = '\0'; >> + strim(new); >> + >> + rcu_assign_pointer(*(char **)file->private_data, new); >> + synchronize_rcu(); >> + kfree(old); >> + >> + debugfs_file_put(dentry); >> + return count; >> + >> +error: >> + kfree(new); >> + debugfs_file_put(dentry); >> + return r; >> } > > So you just added write support for ALL debugfs files that use the > string interface, what did you just allow to break? Not really. According to the existing code, the write support for strings is enabled only when the file is created with +w permissions. For read-only files, we use fops_str_ro, which is the case for all existing string files: $ git grep -w debugfs_create_str | egrep -v "fs/debugfs/file.c|include/linux/debugfs.h" drivers/firmware/arm_scmi/driver.c: debugfs_create_str("instance_name", 0400, top_dentry, drivers/firmware/arm_scmi/driver.c: debugfs_create_str("type", 0400, trans, (char **)&dbg->type); drivers/opp/debugfs.c: debugfs_create_str("of_name", S_IRUGO, d, (char **)&opp->of_name); For fops_str_ro, the .write function is not implemented, so nothing should break? > I recommend just using your own debugfs file function instead, as this > could cause bad problems, right? Agree, and that should be exactly what this patch does. > Are you sure that all string calls can > handle the variable be freed underneath it like this call will allow to > happen? Looks fine, at least for this patch-set. Thanks, Georgi ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() 2023-08-12 10:40 ` Greg KH 2023-08-12 13:25 ` Georgi Djakov @ 2023-08-18 10:05 ` Georgi Djakov 2023-08-22 17:46 ` Greg KH 1 sibling, 1 reply; 11+ messages in thread From: Georgi Djakov @ 2023-08-18 10:05 UTC (permalink / raw) To: Greg KH, Mike Tipton Cc: rafael, corbet, linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti Hi Greg, On 12.08.23 13:40, Greg KH wrote: > On Mon, Aug 07, 2023 at 07:29:12AM -0700, Mike Tipton wrote: >> Currently, debugfs_create_str() only supports reading strings from >> debugfs. Add support for writing them as well. >> >> Based on original implementation by Peter Zijlstra [0]. Write support >> was present in the initial patch version, but dropped in v2 due to lack >> of users. We have a user now, so reintroduce it. >> >> [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/ >> >> Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com> >> --- >> fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++-- >> 1 file changed, 46 insertions(+), 2 deletions(-) >> >> diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c >> index b7711888dd17..87b3753aa4b1 100644 >> --- a/fs/debugfs/file.c >> +++ b/fs/debugfs/file.c >> @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str); >> static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf, >> size_t count, loff_t *ppos) >> { >> - /* This is really only for read-only strings */ >> - return -EINVAL; >> + struct dentry *dentry = F_DENTRY(file); >> + char *old, *new = NULL; >> + int pos = *ppos; >> + int r; >> + >> + r = debugfs_file_get(dentry); >> + if (unlikely(r)) >> + return r; >> + >> + old = *(char **)file->private_data; >> + >> + /* only allow strict concatenation */ >> + r = -EINVAL; >> + if (pos && pos != strlen(old)) >> + goto error; >> + >> + r = -E2BIG; >> + if (pos + count + 1 > PAGE_SIZE) >> + goto error; >> + >> + r = -ENOMEM; >> + new = kmalloc(pos + count + 1, GFP_KERNEL); >> + if (!new) >> + goto error; >> + >> + if (pos) >> + memcpy(new, old, pos); >> + >> + r = -EFAULT; >> + if (copy_from_user(new + pos, user_buf, count)) >> + goto error; >> + >> + new[pos + count] = '\0'; >> + strim(new); >> + >> + rcu_assign_pointer(*(char **)file->private_data, new); >> + synchronize_rcu(); >> + kfree(old); >> + >> + debugfs_file_put(dentry); >> + return count; >> + >> +error: >> + kfree(new); >> + debugfs_file_put(dentry); >> + return r; >> } > > So you just added write support for ALL debugfs files that use the > string interface, what did you just allow to break? Not true. Write support is added only for debugfs string files that are created with +w permissions. All existing files are created as read-only and use the fops_str_ro ops. > I recommend just using your own debugfs file function instead, as this > could cause bad problems, right? Are you sure that all string calls can > handle the variable be freed underneath it like this call will allow to > happen? > > So I wouldn't recommend doing this, sorry. > Maybe you missed the fact that the different file ops are already there and are selected based on permissions: > static const struct file_operations fops_str = { > .read = debugfs_read_file_str, > .write = debugfs_write_file_str, > .open = simple_open, > .llseek = default_llseek, > }; > > static const struct file_operations fops_str_ro = { > .read = debugfs_read_file_str, > .open = simple_open, > .llseek = default_llseek, > }; > > static const struct file_operations fops_str_wo = { > .write = debugfs_write_file_str, > .open = simple_open, > .llseek = default_llseek, > }; ...so this patch is doing exactly what you suggested? If you agree, could you ack it again please? Thanks, Georgi ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() 2023-08-18 10:05 ` Georgi Djakov @ 2023-08-22 17:46 ` Greg KH 0 siblings, 0 replies; 11+ messages in thread From: Greg KH @ 2023-08-22 17:46 UTC (permalink / raw) To: Georgi Djakov Cc: Mike Tipton, rafael, corbet, linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti On Fri, Aug 18, 2023 at 01:05:57PM +0300, Georgi Djakov wrote: > Hi Greg, > > On 12.08.23 13:40, Greg KH wrote: > > On Mon, Aug 07, 2023 at 07:29:12AM -0700, Mike Tipton wrote: > > > Currently, debugfs_create_str() only supports reading strings from > > > debugfs. Add support for writing them as well. > > > > > > Based on original implementation by Peter Zijlstra [0]. Write support > > > was present in the initial patch version, but dropped in v2 due to lack > > > of users. We have a user now, so reintroduce it. > > > > > > [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/ > > > > > > Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com> > > > --- > > > fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++-- > > > 1 file changed, 46 insertions(+), 2 deletions(-) > > > > > > diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c > > > index b7711888dd17..87b3753aa4b1 100644 > > > --- a/fs/debugfs/file.c > > > +++ b/fs/debugfs/file.c > > > @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str); > > > static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf, > > > size_t count, loff_t *ppos) > > > { > > > - /* This is really only for read-only strings */ > > > - return -EINVAL; > > > + struct dentry *dentry = F_DENTRY(file); > > > + char *old, *new = NULL; > > > + int pos = *ppos; > > > + int r; > > > + > > > + r = debugfs_file_get(dentry); > > > + if (unlikely(r)) > > > + return r; > > > + > > > + old = *(char **)file->private_data; > > > + > > > + /* only allow strict concatenation */ > > > + r = -EINVAL; > > > + if (pos && pos != strlen(old)) > > > + goto error; > > > + > > > + r = -E2BIG; > > > + if (pos + count + 1 > PAGE_SIZE) > > > + goto error; > > > + > > > + r = -ENOMEM; > > > + new = kmalloc(pos + count + 1, GFP_KERNEL); > > > + if (!new) > > > + goto error; > > > + > > > + if (pos) > > > + memcpy(new, old, pos); > > > + > > > + r = -EFAULT; > > > + if (copy_from_user(new + pos, user_buf, count)) > > > + goto error; > > > + > > > + new[pos + count] = '\0'; > > > + strim(new); > > > + > > > + rcu_assign_pointer(*(char **)file->private_data, new); > > > + synchronize_rcu(); > > > + kfree(old); > > > + > > > + debugfs_file_put(dentry); > > > + return count; > > > + > > > +error: > > > + kfree(new); > > > + debugfs_file_put(dentry); > > > + return r; > > > } > > > > So you just added write support for ALL debugfs files that use the > > string interface, what did you just allow to break? > > Not true. Write support is added only for debugfs string files that are > created with +w permissions. All existing files are created as read-only > and use the fops_str_ro ops. > > > I recommend just using your own debugfs file function instead, as this > > could cause bad problems, right? Are you sure that all string calls can > > handle the variable be freed underneath it like this call will allow to > > happen? > > > > So I wouldn't recommend doing this, sorry. > > > > Maybe you missed the fact that the different file ops are already there > and are selected based on permissions: > > > static const struct file_operations fops_str = { > > .read = debugfs_read_file_str, > > .write = debugfs_write_file_str, > > .open = simple_open, > > .llseek = default_llseek, > > }; > > > > static const struct file_operations fops_str_ro = { > > .read = debugfs_read_file_str, > > .open = simple_open, > > .llseek = default_llseek, > > }; > > > > static const struct file_operations fops_str_wo = { > > .write = debugfs_write_file_str, > > .open = simple_open, > > .llseek = default_llseek, > > }; > > ...so this patch is doing exactly what you suggested? If you agree, > could you ack it again please? Yes, I did miss that, sorry, my appologies for dragging this out so long: Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 2/3] interconnect: Reintroduce icc_get() 2023-08-07 14:29 [PATCH v3 0/3] Add interconnect debugfs client Mike Tipton 2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton @ 2023-08-07 14:29 ` Mike Tipton 2023-08-07 14:29 ` [PATCH v3 3/3] interconnect: Add debugfs test client Mike Tipton 2 siblings, 0 replies; 11+ messages in thread From: Mike Tipton @ 2023-08-07 14:29 UTC (permalink / raw) To: djakov, gregkh, rafael, corbet Cc: linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti, Mike Tipton The original icc_get() that took integer node IDs was removed due to lack of users. Reintroduce a new version that takes string node names, which is needed for the debugfs client. Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com> --- drivers/interconnect/core.c | 63 +++++++++++++++++++++++++++++++++ drivers/interconnect/internal.h | 2 ++ 2 files changed, 65 insertions(+) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 5fac448c28fd..fc1461dfc61b 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -147,6 +147,21 @@ static struct icc_node *node_find(const int id) return idr_find(&icc_idr, id); } +static struct icc_node *node_find_by_name(const char *name) +{ + struct icc_provider *provider; + struct icc_node *n; + + list_for_each_entry(provider, &icc_providers, provider_list) { + list_for_each_entry(n, &provider->nodes, node_list) { + if (!strcmp(n->name, name)) + return n; + } + } + + return NULL; +} + static struct icc_path *path_init(struct device *dev, struct icc_node *dst, ssize_t num_nodes) { @@ -561,6 +576,54 @@ struct icc_path *of_icc_get(struct device *dev, const char *name) } EXPORT_SYMBOL_GPL(of_icc_get); +/** + * icc_get() - get a path handle between two endpoints + * @dev: device pointer for the consumer device + * @src: source node name + * @dst: destination node name + * + * This function will search for a path between two endpoints and return an + * icc_path handle on success. Use icc_put() to release constraints when they + * are not needed anymore. + * + * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned + * when the API is disabled. + */ +struct icc_path *icc_get(struct device *dev, const char *src, const char *dst) +{ + struct icc_node *src_node, *dst_node; + struct icc_path *path = ERR_PTR(-EPROBE_DEFER); + + mutex_lock(&icc_lock); + + src_node = node_find_by_name(src); + if (!src_node) { + dev_err(dev, "%s: invalid src=%s\n", __func__, src); + goto out; + } + + dst_node = node_find_by_name(dst); + if (!dst_node) { + dev_err(dev, "%s: invalid dst=%s\n", __func__, dst); + goto out; + } + + path = path_find(dev, src_node, dst_node); + if (IS_ERR(path)) { + dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); + goto out; + } + + path->name = kasprintf(GFP_KERNEL, "%s-%s", src_node->name, dst_node->name); + if (!path->name) { + kfree(path); + path = ERR_PTR(-ENOMEM); + } +out: + mutex_unlock(&icc_lock); + return path; +} + /** * icc_set_tag() - set an optional tag on a path * @path: the path we want to tag diff --git a/drivers/interconnect/internal.h b/drivers/interconnect/internal.h index f5f82a5c939e..95d6ba27bf78 100644 --- a/drivers/interconnect/internal.h +++ b/drivers/interconnect/internal.h @@ -41,4 +41,6 @@ struct icc_path { struct icc_req reqs[]; }; +struct icc_path *icc_get(struct device *dev, const char *src, const char *dst); + #endif -- 2.17.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 3/3] interconnect: Add debugfs test client 2023-08-07 14:29 [PATCH v3 0/3] Add interconnect debugfs client Mike Tipton 2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton 2023-08-07 14:29 ` [PATCH v3 2/3] interconnect: Reintroduce icc_get() Mike Tipton @ 2023-08-07 14:29 ` Mike Tipton 2 siblings, 0 replies; 11+ messages in thread From: Mike Tipton @ 2023-08-07 14:29 UTC (permalink / raw) To: djakov, gregkh, rafael, corbet Cc: linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti, Mike Tipton It's often useful during test, debug, and development to issue path votes from shell. Add a debugfs client for this purpose. Example usage: cd /sys/kernel/debug/interconnect/test-client/ # Configure node endpoints for the path from CPU to DDR on # qcom/sm8550. echo chm_apps > src_node echo ebi > dst_node # Get path between src_node and dst_node. This is only # necessary after updating the node endpoints. echo 1 > get # Set desired BW to 1GBps avg and 2GBps peak. echo 1000000 > avg_bw echo 2000000 > peak_bw # Vote for avg_bw and peak_bw on the latest path from "get". # Voting for multiple paths is possible by repeating this # process for different nodes endpoints. echo 1 > commit Allowing userspace to directly enable and set bus rates can be dangerous So, following in the footsteps of the regmap [0] and clk [1] frameworks, keep these userspace controls compile-time disabled without Kconfig options to enable them. Enabling this will require code changes to define INTERCONNECT_ALLOW_WRITE_DEBUGFS. [0] commit 09c6ecd39410 ("regmap: Add support for writing to regmap registers via debugfs") [1] commit 37215da5553e ("clk: Add support for setting clk_rate via debugfs") Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com> --- Documentation/driver-api/interconnect.rst | 25 ++++ drivers/interconnect/Makefile | 2 +- drivers/interconnect/core.c | 3 + drivers/interconnect/debugfs-client.c | 168 ++++++++++++++++++++++ drivers/interconnect/internal.h | 1 + 5 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 drivers/interconnect/debugfs-client.c diff --git a/Documentation/driver-api/interconnect.rst b/Documentation/driver-api/interconnect.rst index 5ed4f57a6bac..a92d0f277a1f 100644 --- a/Documentation/driver-api/interconnect.rst +++ b/Documentation/driver-api/interconnect.rst @@ -113,3 +113,28 @@ through dot to generate diagrams in many graphical formats:: $ cat /sys/kernel/debug/interconnect/interconnect_graph | \ dot -Tsvg > interconnect_graph.svg + +The ``test-client`` directory provides interfaces for issuing BW requests to +any arbitrary path. Note that for safety reasons, this feature is disabled by +default without a Kconfig to enable it. Enabling it requires code changes to +``#define INTERCONNECT_ALLOW_WRITE_DEBUGFS``. Example usage:: + + cd /sys/kernel/debug/interconnect/test-client/ + + # Configure node endpoints for the path from CPU to DDR on + # qcom/sm8550. + echo chm_apps > src_node + echo ebi > dst_node + + # Get path between src_node and dst_node. This is only + # necessary after updating the node endpoints. + echo 1 > get + + # Set desired BW to 1GBps avg and 2GBps peak. + echo 1000000 > avg_bw + echo 2000000 > peak_bw + + # Vote for avg_bw and peak_bw on the latest path from "get". + # Voting for multiple paths is possible by repeating this + # process for different nodes endpoints. + echo 1 > commit diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile index 5604ce351a9f..d0888babb9a1 100644 --- a/drivers/interconnect/Makefile +++ b/drivers/interconnect/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 CFLAGS_core.o := -I$(src) -icc-core-objs := core.o bulk.o +icc-core-objs := core.o bulk.o debugfs-client.o obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT_IMX) += imx/ diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index fc1461dfc61b..9e12bb5e523d 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -1116,6 +1116,9 @@ static int __init icc_init(void) icc_debugfs_dir, NULL, &icc_summary_fops); debugfs_create_file("interconnect_graph", 0444, icc_debugfs_dir, NULL, &icc_graph_fops); + + icc_debugfs_client_init(icc_debugfs_dir); + return 0; } diff --git a/drivers/interconnect/debugfs-client.c b/drivers/interconnect/debugfs-client.c new file mode 100644 index 000000000000..bc3fd8a7b9eb --- /dev/null +++ b/drivers/interconnect/debugfs-client.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ +#include <linux/debugfs.h> +#include <linux/interconnect.h> +#include <linux/platform_device.h> + +#include "internal.h" + +/* + * This can be dangerous, therefore don't provide any real compile time + * configuration option for this feature. + * People who want to use this will need to modify the source code directly. + */ +#undef INTERCONNECT_ALLOW_WRITE_DEBUGFS + +#if defined(INTERCONNECT_ALLOW_WRITE_DEBUGFS) && defined(CONFIG_DEBUG_FS) + +static LIST_HEAD(debugfs_paths); +static DEFINE_MUTEX(debugfs_lock); + +static struct platform_device *pdev; +static struct icc_path *cur_path; + +static char *src_node; +static char *dst_node; +static u32 avg_bw; +static u32 peak_bw; +static u32 tag; + +struct debugfs_path { + const char *src; + const char *dst; + struct icc_path *path; + struct list_head list; +}; + +static struct icc_path *get_path(const char *src, const char *dst) +{ + struct debugfs_path *path; + + list_for_each_entry(path, &debugfs_paths, list) { + if (!strcmp(path->src, src) && !strcmp(path->dst, dst)) + return path->path; + } + + return NULL; +} + +static int icc_get_set(void *data, u64 val) +{ + struct debugfs_path *debugfs_path; + char *src, *dst; + int ret = 0; + + mutex_lock(&debugfs_lock); + + rcu_read_lock(); + src = rcu_dereference(src_node); + dst = rcu_dereference(dst_node); + + /* + * If we've already looked up a path, then use the existing one instead + * of calling icc_get() again. This allows for updating previous BW + * votes when "get" is written to multiple times for multiple paths. + */ + cur_path = get_path(src, dst); + if (cur_path) { + rcu_read_unlock(); + goto out; + } + + src = kstrdup(src, GFP_ATOMIC); + dst = kstrdup(dst, GFP_ATOMIC); + rcu_read_unlock(); + + if (!src || !dst) { + ret = -ENOMEM; + goto err_free; + } + + cur_path = icc_get(&pdev->dev, src, dst); + if (IS_ERR(cur_path)) { + ret = PTR_ERR(cur_path); + goto err_free; + } + + debugfs_path = kzalloc(sizeof(*debugfs_path), GFP_KERNEL); + if (!debugfs_path) { + ret = -ENOMEM; + goto err_put; + } + + debugfs_path->path = cur_path; + debugfs_path->src = src; + debugfs_path->dst = dst; + list_add_tail(&debugfs_path->list, &debugfs_paths); + + goto out; + +err_put: + icc_put(cur_path); +err_free: + kfree(src); + kfree(dst); +out: + mutex_unlock(&debugfs_lock); + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(icc_get_fops, NULL, icc_get_set, "%llu\n"); + +static int icc_commit_set(void *data, u64 val) +{ + int ret; + + mutex_lock(&debugfs_lock); + + if (IS_ERR_OR_NULL(cur_path)) { + ret = PTR_ERR(cur_path); + goto out; + } + + icc_set_tag(cur_path, tag); + ret = icc_set_bw(cur_path, avg_bw, peak_bw); +out: + mutex_unlock(&debugfs_lock); + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(icc_commit_fops, NULL, icc_commit_set, "%llu\n"); + +int icc_debugfs_client_init(struct dentry *icc_dir) +{ + struct dentry *client_dir; + int ret; + + pdev = platform_device_alloc("icc-debugfs-client", PLATFORM_DEVID_NONE); + + ret = platform_device_add(pdev); + if (ret) { + pr_err("%s: failed to add platform device: %d\n", __func__, ret); + platform_device_put(pdev); + return ret; + } + + client_dir = debugfs_create_dir("test_client", icc_dir); + + debugfs_create_str("src_node", 0600, client_dir, &src_node); + debugfs_create_str("dst_node", 0600, client_dir, &dst_node); + debugfs_create_file("get", 0200, client_dir, NULL, &icc_get_fops); + debugfs_create_u32("avg_bw", 0600, client_dir, &avg_bw); + debugfs_create_u32("peak_bw", 0600, client_dir, &peak_bw); + debugfs_create_u32("tag", 0600, client_dir, &tag); + debugfs_create_file("commit", 0200, client_dir, NULL, &icc_commit_fops); + + return 0; +} + +#else + +int icc_debugfs_client_init(struct dentry *icc_dir) +{ + return 0; +} + +#endif diff --git a/drivers/interconnect/internal.h b/drivers/interconnect/internal.h index 95d6ba27bf78..3b2cfd32e449 100644 --- a/drivers/interconnect/internal.h +++ b/drivers/interconnect/internal.h @@ -42,5 +42,6 @@ struct icc_path { }; struct icc_path *icc_get(struct device *dev, const char *src, const char *dst); +int icc_debugfs_client_init(struct dentry *icc_dir); #endif -- 2.17.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2023-08-22 17:46 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-08-07 14:29 [PATCH v3 0/3] Add interconnect debugfs client Mike Tipton 2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton 2023-08-11 7:46 ` Georgi Djakov 2023-08-12 10:36 ` Greg KH 2023-08-12 10:37 ` Greg KH 2023-08-12 10:40 ` Greg KH 2023-08-12 13:25 ` Georgi Djakov 2023-08-18 10:05 ` Georgi Djakov 2023-08-22 17:46 ` Greg KH 2023-08-07 14:29 ` [PATCH v3 2/3] interconnect: Reintroduce icc_get() Mike Tipton 2023-08-07 14:29 ` [PATCH v3 3/3] interconnect: Add debugfs test client Mike Tipton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).