All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cezary Rojewski <cezary.rojewski@intel.com>
To: andy@kernel.org, broonie@kernel.org
Cc: alsa-devel@alsa-project.org, tiwai@suse.com, perex@perex.cz,
	amadeuszx.slawinski@linux.intel.com,
	pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com,
	peter.ujfalusi@linux.intel.com,
	ranjani.sridharan@linux.intel.com, linux-kernel@vger.kernel.org,
	lgirdwood@gmail.com, kai.vehmanen@linux.intel.com,
	yung-chuan.liao@linux.intel.com,
	Cezary Rojewski <cezary.rojewski@intel.com>
Subject: [PATCH 1/2] lib/string_helpers: Introduce strsplit_u32()
Date: Thu,  7 Jul 2022 11:13:00 +0200	[thread overview]
Message-ID: <20220707091301.1282291-1-cezary.rojewski@intel.com> (raw)

Add strsplit_u32() and its __user variant to allow for splitting
specified string into array of u32 tokens.

Originally this functionality was added for the SOF sound driver. As
more users are on the horizon, relocate it so it becomes a common good.

Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 include/linux/string_helpers.h    |  3 +
 lib/string_helpers.c              | 96 +++++++++++++++++++++++++++++++
 sound/soc/sof/sof-client-probes.c | 51 +---------------
 3 files changed, 100 insertions(+), 50 deletions(-)

diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
index 4d72258d42fd..a4630ddfca27 100644
--- a/include/linux/string_helpers.h
+++ b/include/linux/string_helpers.h
@@ -126,4 +126,7 @@ static inline const char *str_enabled_disabled(bool v)
 	return v ? "enabled" : "disabled";
 }
 
+int strsplit_u32(const char *str, const char *delim, u32 **tkns, size_t *num_tkns);
+int strsplit_u32_user(const char __user *from, size_t count, loff_t *ppos, const char *delim,
+		      u32 **tkns, size_t *num_tkns);
 #endif
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 5ed3beb066e6..bb24f0c62539 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -984,3 +984,99 @@ void fortify_panic(const char *name)
 }
 EXPORT_SYMBOL(fortify_panic);
 #endif /* CONFIG_FORTIFY_SOURCE */
+
+/**
+ * strsplit_u32 - Split string into sequence of u32 tokens
+ * @str:	The string to split into tokens.
+ * @delim:	The string containing delimiter characters.
+ * @tkns:	Returned u32 sequence pointer.
+ * @num_tkns:	Returned number of tokens obtained.
+ *
+ * On success @num_tkns and @tkns are assigned the number of tokens extracted
+ * and the array itself respectively.
+ * Caller takes responsibility for freeing @tkns when no longer needed.
+ */
+int strsplit_u32(const char *str, const char *delim, u32 **tkns, size_t *num_tkns)
+{
+	size_t max_count = 32;
+	size_t count = 0;
+	char *s, **p;
+	u32 *buf, *tmp;
+	int ret = 0;
+
+	p = (char **)&str;
+	*tkns = NULL;
+	*num_tkns = 0;
+
+	buf = kcalloc(max_count, sizeof(*buf), GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	while ((s = strsep(p, delim)) != NULL) {
+		ret = kstrtouint(s, 0, buf + count);
+		if (ret)
+			goto free_buf;
+
+		if (++count > max_count) {
+			max_count *= 2;
+			tmp = krealloc(buf, max_count * sizeof(*buf), GFP_KERNEL);
+			if (!tmp) {
+				ret = -ENOMEM;
+				goto free_buf;
+			}
+			buf = tmp;
+		}
+	}
+
+	if (!count)
+		goto free_buf;
+	*tkns = kmemdup(buf, count * sizeof(*buf), GFP_KERNEL);
+	if (*tkns == NULL) {
+		ret = -ENOMEM;
+		goto free_buf;
+	}
+	*num_tkns = count;
+
+free_buf:
+	kfree(buf);
+	return ret;
+}
+EXPORT_SYMBOL(strsplit_u32);
+
+/**
+ * strsplit_u32_user - Split string into sequence of u32 tokens
+ * @from:	The user space buffer to read from
+ * @ppos:	The current position in the buffer
+ * @count:	The maximum number of bytes to read
+ * @delim:	The string containing delimiter characters.
+ * @tkns:	Returned u32 sequence pointer.
+ * @num_tkns:	Returned number of tokens obtained.
+ *
+ * On success @num_tkns and @tkns are assigned the number of tokens extracted
+ * and the array itself respectively.
+ * Caller takes responsibility for freeing @tkns when no longer needed.
+ */
+int strsplit_u32_user(const char __user *from, size_t count, loff_t *ppos, const char *delim,
+		      u32 **tkns, size_t *num_tkns)
+{
+	char *buf;
+	int ret;
+
+	buf = kmalloc(count + 1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = simple_write_to_buffer(buf, count, ppos, from, count);
+	if (ret != count) {
+		ret = (ret < 0) ? ret : -EIO;
+		goto free_buf;
+	}
+
+	buf[count] = '\0';
+	ret = strsplit_u32(buf, delim, tkns, num_tkns);
+
+free_buf:
+	kfree(buf);
+	return ret;
+}
+EXPORT_SYMBOL(strsplit_u32_user);
diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c
index 1f1ea93a7fbf..48ebbe58e2b9 100644
--- a/sound/soc/sof/sof-client-probes.c
+++ b/sound/soc/sof/sof-client-probes.c
@@ -12,6 +12,7 @@
 #include <linux/debugfs.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/string_helpers.h>
 #include <sound/soc.h>
 #include <sound/sof/header.h>
 #include "sof-client.h"
@@ -410,56 +411,6 @@ static const struct snd_compress_ops sof_probes_compressed_ops = {
 	.copy = sof_probes_compr_copy,
 };
 
-/**
- * strsplit_u32 - Split string into sequence of u32 tokens
- * @buf:	String to split into tokens.
- * @delim:	String containing delimiter characters.
- * @tkns:	Returned u32 sequence pointer.
- * @num_tkns:	Returned number of tokens obtained.
- */
-static int strsplit_u32(char *buf, const char *delim, u32 **tkns, size_t *num_tkns)
-{
-	char *s;
-	u32 *data, *tmp;
-	size_t count = 0;
-	size_t cap = 32;
-	int ret = 0;
-
-	*tkns = NULL;
-	*num_tkns = 0;
-	data = kcalloc(cap, sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	while ((s = strsep(&buf, delim)) != NULL) {
-		ret = kstrtouint(s, 0, data + count);
-		if (ret)
-			goto exit;
-		if (++count >= cap) {
-			cap *= 2;
-			tmp = krealloc(data, cap * sizeof(*data), GFP_KERNEL);
-			if (!tmp) {
-				ret = -ENOMEM;
-				goto exit;
-			}
-			data = tmp;
-		}
-	}
-
-	if (!count)
-		goto exit;
-	*tkns = kmemdup(data, count * sizeof(*data), GFP_KERNEL);
-	if (!(*tkns)) {
-		ret = -ENOMEM;
-		goto exit;
-	}
-	*num_tkns = count;
-
-exit:
-	kfree(data);
-	return ret;
-}
-
 static int tokenize_input(const char __user *from, size_t count,
 			  loff_t *ppos, u32 **tkns, size_t *num_tkns)
 {
-- 
2.25.1


WARNING: multiple messages have this Message-ID (diff)
From: Cezary Rojewski <cezary.rojewski@intel.com>
To: andy@kernel.org, broonie@kernel.org
Cc: alsa-devel@alsa-project.org, kai.vehmanen@linux.intel.com,
	lgirdwood@gmail.com, linux-kernel@vger.kernel.org,
	Cezary Rojewski <cezary.rojewski@intel.com>,
	pierre-louis.bossart@linux.intel.com, tiwai@suse.com,
	hdegoede@redhat.com, yung-chuan.liao@linux.intel.com,
	ranjani.sridharan@linux.intel.com,
	amadeuszx.slawinski@linux.intel.com,
	peter.ujfalusi@linux.intel.com
Subject: [PATCH 1/2] lib/string_helpers: Introduce strsplit_u32()
Date: Thu,  7 Jul 2022 11:13:00 +0200	[thread overview]
Message-ID: <20220707091301.1282291-1-cezary.rojewski@intel.com> (raw)

Add strsplit_u32() and its __user variant to allow for splitting
specified string into array of u32 tokens.

Originally this functionality was added for the SOF sound driver. As
more users are on the horizon, relocate it so it becomes a common good.

Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 include/linux/string_helpers.h    |  3 +
 lib/string_helpers.c              | 96 +++++++++++++++++++++++++++++++
 sound/soc/sof/sof-client-probes.c | 51 +---------------
 3 files changed, 100 insertions(+), 50 deletions(-)

diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
index 4d72258d42fd..a4630ddfca27 100644
--- a/include/linux/string_helpers.h
+++ b/include/linux/string_helpers.h
@@ -126,4 +126,7 @@ static inline const char *str_enabled_disabled(bool v)
 	return v ? "enabled" : "disabled";
 }
 
+int strsplit_u32(const char *str, const char *delim, u32 **tkns, size_t *num_tkns);
+int strsplit_u32_user(const char __user *from, size_t count, loff_t *ppos, const char *delim,
+		      u32 **tkns, size_t *num_tkns);
 #endif
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 5ed3beb066e6..bb24f0c62539 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -984,3 +984,99 @@ void fortify_panic(const char *name)
 }
 EXPORT_SYMBOL(fortify_panic);
 #endif /* CONFIG_FORTIFY_SOURCE */
+
+/**
+ * strsplit_u32 - Split string into sequence of u32 tokens
+ * @str:	The string to split into tokens.
+ * @delim:	The string containing delimiter characters.
+ * @tkns:	Returned u32 sequence pointer.
+ * @num_tkns:	Returned number of tokens obtained.
+ *
+ * On success @num_tkns and @tkns are assigned the number of tokens extracted
+ * and the array itself respectively.
+ * Caller takes responsibility for freeing @tkns when no longer needed.
+ */
+int strsplit_u32(const char *str, const char *delim, u32 **tkns, size_t *num_tkns)
+{
+	size_t max_count = 32;
+	size_t count = 0;
+	char *s, **p;
+	u32 *buf, *tmp;
+	int ret = 0;
+
+	p = (char **)&str;
+	*tkns = NULL;
+	*num_tkns = 0;
+
+	buf = kcalloc(max_count, sizeof(*buf), GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	while ((s = strsep(p, delim)) != NULL) {
+		ret = kstrtouint(s, 0, buf + count);
+		if (ret)
+			goto free_buf;
+
+		if (++count > max_count) {
+			max_count *= 2;
+			tmp = krealloc(buf, max_count * sizeof(*buf), GFP_KERNEL);
+			if (!tmp) {
+				ret = -ENOMEM;
+				goto free_buf;
+			}
+			buf = tmp;
+		}
+	}
+
+	if (!count)
+		goto free_buf;
+	*tkns = kmemdup(buf, count * sizeof(*buf), GFP_KERNEL);
+	if (*tkns == NULL) {
+		ret = -ENOMEM;
+		goto free_buf;
+	}
+	*num_tkns = count;
+
+free_buf:
+	kfree(buf);
+	return ret;
+}
+EXPORT_SYMBOL(strsplit_u32);
+
+/**
+ * strsplit_u32_user - Split string into sequence of u32 tokens
+ * @from:	The user space buffer to read from
+ * @ppos:	The current position in the buffer
+ * @count:	The maximum number of bytes to read
+ * @delim:	The string containing delimiter characters.
+ * @tkns:	Returned u32 sequence pointer.
+ * @num_tkns:	Returned number of tokens obtained.
+ *
+ * On success @num_tkns and @tkns are assigned the number of tokens extracted
+ * and the array itself respectively.
+ * Caller takes responsibility for freeing @tkns when no longer needed.
+ */
+int strsplit_u32_user(const char __user *from, size_t count, loff_t *ppos, const char *delim,
+		      u32 **tkns, size_t *num_tkns)
+{
+	char *buf;
+	int ret;
+
+	buf = kmalloc(count + 1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = simple_write_to_buffer(buf, count, ppos, from, count);
+	if (ret != count) {
+		ret = (ret < 0) ? ret : -EIO;
+		goto free_buf;
+	}
+
+	buf[count] = '\0';
+	ret = strsplit_u32(buf, delim, tkns, num_tkns);
+
+free_buf:
+	kfree(buf);
+	return ret;
+}
+EXPORT_SYMBOL(strsplit_u32_user);
diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c
index 1f1ea93a7fbf..48ebbe58e2b9 100644
--- a/sound/soc/sof/sof-client-probes.c
+++ b/sound/soc/sof/sof-client-probes.c
@@ -12,6 +12,7 @@
 #include <linux/debugfs.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/string_helpers.h>
 #include <sound/soc.h>
 #include <sound/sof/header.h>
 #include "sof-client.h"
@@ -410,56 +411,6 @@ static const struct snd_compress_ops sof_probes_compressed_ops = {
 	.copy = sof_probes_compr_copy,
 };
 
-/**
- * strsplit_u32 - Split string into sequence of u32 tokens
- * @buf:	String to split into tokens.
- * @delim:	String containing delimiter characters.
- * @tkns:	Returned u32 sequence pointer.
- * @num_tkns:	Returned number of tokens obtained.
- */
-static int strsplit_u32(char *buf, const char *delim, u32 **tkns, size_t *num_tkns)
-{
-	char *s;
-	u32 *data, *tmp;
-	size_t count = 0;
-	size_t cap = 32;
-	int ret = 0;
-
-	*tkns = NULL;
-	*num_tkns = 0;
-	data = kcalloc(cap, sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	while ((s = strsep(&buf, delim)) != NULL) {
-		ret = kstrtouint(s, 0, data + count);
-		if (ret)
-			goto exit;
-		if (++count >= cap) {
-			cap *= 2;
-			tmp = krealloc(data, cap * sizeof(*data), GFP_KERNEL);
-			if (!tmp) {
-				ret = -ENOMEM;
-				goto exit;
-			}
-			data = tmp;
-		}
-	}
-
-	if (!count)
-		goto exit;
-	*tkns = kmemdup(data, count * sizeof(*data), GFP_KERNEL);
-	if (!(*tkns)) {
-		ret = -ENOMEM;
-		goto exit;
-	}
-	*num_tkns = count;
-
-exit:
-	kfree(data);
-	return ret;
-}
-
 static int tokenize_input(const char __user *from, size_t count,
 			  loff_t *ppos, u32 **tkns, size_t *num_tkns)
 {
-- 
2.25.1


             reply	other threads:[~2022-07-07  9:03 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-07  9:13 Cezary Rojewski [this message]
2022-07-07  9:13 ` [PATCH 1/2] lib/string_helpers: Introduce strsplit_u32() Cezary Rojewski
2022-07-07  9:13 ` [PATCH 2/2] ASoC: SOF: Remove tokenize_input() Cezary Rojewski
2022-07-07  9:13   ` Cezary Rojewski
2022-07-07 13:51 ` [PATCH 1/2] lib/string_helpers: Introduce strsplit_u32() Péter Ujfalusi
2022-07-07 13:51   ` Péter Ujfalusi
2022-07-08 11:33   ` Cezary Rojewski
2022-07-08 11:33     ` Cezary Rojewski
2022-07-08 10:22 ` Andy Shevchenko
2022-07-08 10:22   ` Andy Shevchenko
2022-07-08 11:29   ` Andy Shevchenko
2022-07-08 11:29     ` Andy Shevchenko
2022-07-08 11:32   ` Cezary Rojewski
2022-07-08 11:32     ` Cezary Rojewski
2022-07-08 11:46     ` Andy Shevchenko
2022-07-08 11:46       ` Andy Shevchenko
2022-07-08 11:51       ` Andy Shevchenko
2022-07-08 11:51         ` Andy Shevchenko
2022-07-08 12:13       ` Cezary Rojewski
2022-07-08 12:13         ` Cezary Rojewski
2022-07-08 12:30         ` Andy Shevchenko
2022-07-08 12:30           ` Andy Shevchenko
2022-07-08 12:35           ` Péter Ujfalusi
2022-07-08 12:35             ` Péter Ujfalusi
2022-07-08 15:25             ` Andy Shevchenko
2022-07-08 15:25               ` Andy Shevchenko
2022-07-08 15:28               ` Andy Shevchenko
2022-07-08 15:28                 ` Andy Shevchenko
2022-07-08 16:32               ` Cezary Rojewski
2022-07-08 16:32                 ` Cezary Rojewski
2022-07-08 16:49                 ` Andy Shevchenko
2022-07-08 16:49                   ` Andy Shevchenko
2022-07-09  8:45                   ` Cezary Rojewski
2022-07-09  8:45                     ` Cezary Rojewski
2022-07-09 20:42                     ` Andy Shevchenko
2022-07-09 20:42                       ` Andy Shevchenko
2022-07-12 13:51                       ` Cezary Rojewski
2022-07-12 13:51                         ` Cezary Rojewski
2022-07-12 13:59                         ` Andy Shevchenko
2022-07-12 13:59                           ` Andy Shevchenko
2022-07-12 14:02                         ` Mark Brown
2022-07-12 14:02                           ` Mark Brown
2022-07-12 14:24                         ` Andy Shevchenko
2022-07-12 14:24                           ` Andy Shevchenko
2022-07-19 11:40                           ` Cezary Rojewski
2022-07-19 11:40                             ` Cezary Rojewski
2022-08-09  9:55                           ` Cezary Rojewski
2022-08-09  9:55                             ` Cezary Rojewski
2022-08-09 15:23                             ` Andy Shevchenko
2022-08-09 15:23                               ` Andy Shevchenko
2022-08-16  9:28                               ` Cezary Rojewski
2022-08-16  9:28                                 ` Cezary Rojewski
2022-08-25 15:09                                 ` Andy Shevchenko
2022-08-25 15:09                                   ` Andy Shevchenko
2022-08-25 16:44                                   ` Cezary Rojewski
2022-08-25 16:44                                     ` Cezary Rojewski
2022-07-13  9:14                 ` David Laight
2022-07-13  9:14                   ` David Laight
2022-07-13  9:38                   ` Andy Shevchenko
2022-07-13  9:38                     ` Andy Shevchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220707091301.1282291-1-cezary.rojewski@intel.com \
    --to=cezary.rojewski@intel.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=amadeuszx.slawinski@linux.intel.com \
    --cc=andy@kernel.org \
    --cc=broonie@kernel.org \
    --cc=hdegoede@redhat.com \
    --cc=kai.vehmanen@linux.intel.com \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=peter.ujfalusi@linux.intel.com \
    --cc=pierre-louis.bossart@linux.intel.com \
    --cc=ranjani.sridharan@linux.intel.com \
    --cc=tiwai@suse.com \
    --cc=yung-chuan.liao@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.