linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] Use clk bulk API in exynos5433 drivers
       [not found] <CGME20180219154456eucas1p178a82b3bb643028dc7c99ccca9c6eaca@eucas1p1.samsung.com>
@ 2018-02-19 15:43 ` Maciej Purski
       [not found]   ` <CGME20180219154456eucas1p15f4073beaf61312238f142f217a8bb3c@eucas1p1.samsung.com>
                     ` (7 more replies)
  0 siblings, 8 replies; 18+ messages in thread
From: Maciej Purski @ 2018-02-19 15:43 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, linux-arm-kernel, dri-devel,
	linux-kernel, linux-clk
  Cc: Michael Turquette, Stephen Boyd, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, David Airlie, Kukjin Kim,
	Krzysztof Kozlowski, Mauro Carvalho Chehab,
	Andrzej Pietrasiewicz, Jacek Anaszewski, Kamil Debski,
	Jeongtae Park, Andrzej Hajda, Russell King, Sylwester Nawrocki,
	Thibault Saunier, Javier Martinez Canillas, Hans Verkuil,
	Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Marek Szyprowski,
	Maciej Purski

Hi all,

the main goal of this patchset is to simplify clk management code in
exynos5433 drivers by using clk bulk API. In order to achieve that,
patch #1 adds a new function to clk core, which dynamically allocates
clk_bulk_data array and fills its id fields.

Best regards,

Maciej Purski

Maciej Purski (8):
  clk: Add clk_bulk_alloc functions
  media: s5p-jpeg: Use bulk clk API
  drm/exynos/decon: Use clk bulk API
  drm/exynos/dsi: Use clk bulk API
  drm/exynos: mic: Use clk bulk API
  drm/exynos/hdmi: Use clk bulk API
  [media] exynos-gsc: Use clk bulk API
  [media] s5p-mfc: Use clk bulk API

 drivers/clk/clk-bulk.c                          | 16 +++++
 drivers/clk/clk-devres.c                        | 37 +++++++++--
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c   | 50 +++++----------
 drivers/gpu/drm/exynos/exynos_drm_dsi.c         | 68 +++++++++-----------
 drivers/gpu/drm/exynos/exynos_drm_mic.c         | 44 +++++--------
 drivers/gpu/drm/exynos/exynos_hdmi.c            | 85 ++++++++-----------------
 drivers/media/platform/exynos-gsc/gsc-core.c    | 55 ++++++----------
 drivers/media/platform/exynos-gsc/gsc-core.h    |  2 +-
 drivers/media/platform/s5p-jpeg/jpeg-core.c     | 45 ++++++-------
 drivers/media/platform/s5p-jpeg/jpeg-core.h     |  2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h |  6 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_pm.c     | 41 +++++-------
 include/linux/clk.h                             | 64 +++++++++++++++++++
 13 files changed, 263 insertions(+), 252 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/8] clk: Add clk_bulk_alloc functions
       [not found]   ` <CGME20180219154456eucas1p15f4073beaf61312238f142f217a8bb3c@eucas1p1.samsung.com>
@ 2018-02-19 15:43     ` Maciej Purski
  2018-02-19 16:29       ` Robin Murphy
  2018-02-19 18:22       ` Emil Velikov
  0 siblings, 2 replies; 18+ messages in thread
From: Maciej Purski @ 2018-02-19 15:43 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, linux-arm-kernel, dri-devel,
	linux-kernel, linux-clk
  Cc: Michael Turquette, Stephen Boyd, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, David Airlie, Kukjin Kim,
	Krzysztof Kozlowski, Mauro Carvalho Chehab,
	Andrzej Pietrasiewicz, Jacek Anaszewski, Kamil Debski,
	Jeongtae Park, Andrzej Hajda, Russell King, Sylwester Nawrocki,
	Thibault Saunier, Javier Martinez Canillas, Hans Verkuil,
	Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Marek Szyprowski,
	Maciej Purski

When a driver is going to use clk_bulk_get() function, it has to
initialize an array of clk_bulk_data, by filling its id fields.

Add a new function to the core, which dynamically allocates
clk_bulk_data array and fills its id fields. Add clk_bulk_free()
function, which frees the array allocated by clk_bulk_alloc() function.
Add a managed version of clk_bulk_alloc().

Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
 drivers/clk/clk-bulk.c   | 16 ++++++++++++
 drivers/clk/clk-devres.c | 37 +++++++++++++++++++++++++---
 include/linux/clk.h      | 64 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c
index 4c10456..2f16941 100644
--- a/drivers/clk/clk-bulk.c
+++ b/drivers/clk/clk-bulk.c
@@ -19,6 +19,22 @@
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/export.h>
+#include <linux/slab.h>
+
+struct clk_bulk_data *clk_bulk_alloc(int num_clocks, const char *const *clk_ids)
+{
+	struct clk_bulk_data *ptr;
+	int i;
+
+	ptr = kcalloc(num_clocks, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < num_clocks; i++)
+		ptr[i].id = clk_ids[i];
+
+	return ptr;
+}
 
 void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
 {
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index d854e26..2115b97 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -9,6 +9,39 @@
 #include <linux/export.h>
 #include <linux/gfp.h>
 
+struct clk_bulk_devres {
+	struct clk_bulk_data *clks;
+	int num_clks;
+};
+
+static void devm_clk_alloc_release(struct device *dev, void *res)
+{
+	struct clk_bulk_devres *devres = res;
+
+	clk_bulk_free(devres->clks);
+}
+
+struct clk_bulk_data *devm_clk_bulk_alloc(struct device *dev, int num_clks,
+					  const char *const *clk_ids)
+{
+	struct clk_bulk_data **ptr, *clk_bulk;
+
+	ptr = devres_alloc(devm_clk_alloc_release,
+			   num_clks * sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	clk_bulk = clk_bulk_alloc(num_clks, clk_ids);
+	if (clk_bulk) {
+		*ptr = clk_bulk;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return clk_bulk;
+}
+
 static void devm_clk_release(struct device *dev, void *res)
 {
 	clk_put(*(struct clk **)res);
@@ -34,10 +67,6 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL(devm_clk_get);
 
-struct clk_bulk_devres {
-	struct clk_bulk_data *clks;
-	int num_clks;
-};
 
 static void devm_clk_bulk_release(struct device *dev, void *res)
 {
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 4c4ef9f..7d66f41 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/notifier.h>
+#include <linux/slab.h>
 
 struct device;
 struct clk;
@@ -240,6 +241,52 @@ static inline void clk_bulk_unprepare(int num_clks, struct clk_bulk_data *clks)
 #endif
 
 #ifdef CONFIG_HAVE_CLK
+
+/**
+ * clk_bulk_alloc - allocates an array of clk_bulk_data and fills their
+ *		    id field
+ * @num_clks: number of clk_bulk_data
+ * @clk_ids: array of clock consumer ID's
+ *
+ * This function allows drivers to dynamically create an array of clk_bulk_data
+ * and fill their id field in one operation. If successful, it allows calling
+ * clk_bulk_get on the pointer returned by this function.
+ *
+ * Returns a pointer to a clk_bulk_data array, or valid IS_ERR() condition
+ * containing errno.
+ */
+struct clk_bulk_data *clk_bulk_alloc(int num_clks, const char *const *clk_ids);
+
+/**
+ * devm_clk_bulk_alloc - allocates an array of clk_bulk_data and fills their
+ *			 id field
+ * @dev: device for clock "consumer"
+ * @num_clks: number of clk_bulk_data
+ * @clk_ids: array of clock consumer ID's
+ *
+ * This function allows drivers to dynamically create an array of clk_bulk_data
+ * and fill their id field in one operation with management, the array will
+ * automatically be freed when the device is unbound. If successful, it allows
+ * calling clk_bulk_get on the pointer returned by this function.
+ *
+ * Returns a pointer to a clk_bulk_data array, or valid IS_ERR() condition
+ * containing errno.
+ */
+struct clk_bulk_data *devm_clk_bulk_alloc(struct device *dev, int num_clks,
+					  const char * const *clk_ids);
+
+/**
+ * clk_bulk_free - frees the array of clk_bulk_data
+ * @clks: pointer to clk_bulk_data array
+ *
+ * This function frees the array allocated by clk_bulk_data. It must be called
+ * when all clks are freed.
+ */
+static inline void clk_bulk_free(struct clk_bulk_data *clks)
+{
+	kfree(clks);
+}
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -598,6 +645,23 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id);
 
 #else /* !CONFIG_HAVE_CLK */
 
+static inline struct clk_bulk_data *clk_bulk_alloc(int num_clks,
+						   const char **clk_ids)
+{
+	return NULL;
+}
+
+static inline struct clk_bulk_data *devm_clk_bulk_alloc(struct device *dev,
+							int num_clks,
+							const char **clk_ids)
+{
+	return NULL;
+}
+
+static inline void clk_bulk_free(struct clk_bulk_data *clks)
+{
+}
+
 static inline struct clk *clk_get(struct device *dev, const char *id)
 {
 	return NULL;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/8] media: s5p-jpeg: Use bulk clk API
       [not found]   ` <CGME20180219154457eucas1p163264992903698a8878aa5abbc8aa17b@eucas1p1.samsung.com>
@ 2018-02-19 15:44     ` Maciej Purski
  2018-02-20  0:22       ` kbuild test robot
  0 siblings, 1 reply; 18+ messages in thread
From: Maciej Purski @ 2018-02-19 15:44 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, linux-arm-kernel, dri-devel,
	linux-kernel, linux-clk
  Cc: Michael Turquette, Stephen Boyd, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, David Airlie, Kukjin Kim,
	Krzysztof Kozlowski, Mauro Carvalho Chehab,
	Andrzej Pietrasiewicz, Jacek Anaszewski, Kamil Debski,
	Jeongtae Park, Andrzej Hajda, Russell King, Sylwester Nawrocki,
	Thibault Saunier, Javier Martinez Canillas, Hans Verkuil,
	Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Marek Szyprowski,
	Maciej Purski

Using bulk clk functions simplifies the driver's code. Use devm_clk_bulk
functions instead of iterating over an array of clks.

Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
 drivers/media/platform/s5p-jpeg/jpeg-core.c | 45 ++++++++++++-----------------
 drivers/media/platform/s5p-jpeg/jpeg-core.h |  2 +-
 2 files changed, 20 insertions(+), 27 deletions(-)

diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 79b63da..681a515 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -2903,7 +2903,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
 {
 	struct s5p_jpeg *jpeg;
 	struct resource *res;
-	int i, ret;
+	int ret;
 
 	/* JPEG IP abstraction struct */
 	jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
@@ -2938,15 +2938,16 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
 	}
 
 	/* clocks */
-	for (i = 0; i < jpeg->variant->num_clocks; i++) {
-		jpeg->clocks[i] = devm_clk_get(&pdev->dev,
-					      jpeg->variant->clk_names[i]);
-		if (IS_ERR(jpeg->clocks[i])) {
-			dev_err(&pdev->dev, "failed to get clock: %s\n",
-				jpeg->variant->clk_names[i]);
-			return PTR_ERR(jpeg->clocks[i]);
-		}
-	}
+	jpeg->clocks = devm_clk_bulk_alloc(&pdev->dev,
+					   jpeg->variant->num_clocks,
+					   jpeg->variant->clk_names);
+	if (IS_ERR(jpeg->clocks))
+		return PTR_ERR(jpeg->clocks);
+
+	ret = devm_clk_bulk_get(&pdev->dev, jpeg->variant->num_clocks,
+				jpeg->clocks);
+	if (ret < 0)
+		return ret;
 
 	/* v4l2 device */
 	ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
@@ -3047,7 +3048,6 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
 static int s5p_jpeg_remove(struct platform_device *pdev)
 {
 	struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
-	int i;
 
 	pm_runtime_disable(jpeg->dev);
 
@@ -3058,8 +3058,8 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
 	v4l2_device_unregister(&jpeg->v4l2_dev);
 
 	if (!pm_runtime_status_suspended(&pdev->dev)) {
-		for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
-			clk_disable_unprepare(jpeg->clocks[i]);
+		clk_bulk_disable_unprepare(jpeg->variant->num_clocks,
+					   jpeg->clocks);
 	}
 
 	return 0;
@@ -3069,10 +3069,8 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
 static int s5p_jpeg_runtime_suspend(struct device *dev)
 {
 	struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
-	int i;
 
-	for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
-		clk_disable_unprepare(jpeg->clocks[i]);
+	clk_bulk_disable_unprepare(jpeg->variant->num_clocks, jpeg->clocks);
 
 	return 0;
 }
@@ -3081,16 +3079,11 @@ static int s5p_jpeg_runtime_resume(struct device *dev)
 {
 	struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
 	unsigned long flags;
-	int i, ret;
-
-	for (i = 0; i < jpeg->variant->num_clocks; i++) {
-		ret = clk_prepare_enable(jpeg->clocks[i]);
-		if (ret) {
-			while (--i >= 0)
-				clk_disable_unprepare(jpeg->clocks[i]);
-			return ret;
-		}
-	}
+	int ret;
+
+	ret = clk_bulk_prepare_enable(jpeg->variant->num_clocks, jpeg->clocks);
+	if (ret)
+		return ret;
 
 	spin_lock_irqsave(&jpeg->slock, flags);
 
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h
index a46465e..dc6ed98 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.h
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.h
@@ -133,7 +133,7 @@ struct s5p_jpeg {
 	void __iomem		*regs;
 	unsigned int		irq;
 	enum exynos4_jpeg_result irq_ret;
-	struct clk		*clocks[JPEG_MAX_CLOCKS];
+	struct clk_bulk_data	*clocks;
 	struct device		*dev;
 	struct s5p_jpeg_variant *variant;
 	u32			irq_status;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/8] drm/exynos/decon: Use clk bulk API
       [not found]   ` <CGME20180219154458eucas1p1b4e728757e78f3d5dde5c9aa565a5d20@eucas1p1.samsung.com>
@ 2018-02-19 15:44     ` Maciej Purski
  0 siblings, 0 replies; 18+ messages in thread
From: Maciej Purski @ 2018-02-19 15:44 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, linux-arm-kernel, dri-devel,
	linux-kernel, linux-clk
  Cc: Michael Turquette, Stephen Boyd, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, David Airlie, Kukjin Kim,
	Krzysztof Kozlowski, Mauro Carvalho Chehab,
	Andrzej Pietrasiewicz, Jacek Anaszewski, Kamil Debski,
	Jeongtae Park, Andrzej Hajda, Russell King, Sylwester Nawrocki,
	Thibault Saunier, Javier Martinez Canillas, Hans Verkuil,
	Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Marek Szyprowski,
	Maciej Purski

Using bulk clk functions simplifies the driver's code. Use devm_clk_bulk
functions instead of iterating over an array of clks.

Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 50 ++++++++-------------------
 1 file changed, 15 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 1c330f2..1760fcb 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -55,7 +55,7 @@ struct decon_context {
 	struct exynos_drm_plane_config	configs[WINDOWS_NR];
 	void __iomem			*addr;
 	struct regmap			*sysreg;
-	struct clk			*clks[ARRAY_SIZE(decon_clks_name)];
+	struct clk_bulk_data		*clks;
 	unsigned int			irq;
 	unsigned int			irq_vsync;
 	unsigned int			irq_lcd_sys;
@@ -485,15 +485,13 @@ static irqreturn_t decon_te_irq_handler(int irq, void *dev_id)
 static void decon_clear_channels(struct exynos_drm_crtc *crtc)
 {
 	struct decon_context *ctx = crtc->ctx;
-	int win, i, ret;
+	int win, ret;
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
-	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
-		ret = clk_prepare_enable(ctx->clks[i]);
-		if (ret < 0)
-			goto err;
-	}
+	ret = clk_bulk_prepare_enable(ARRAY_SIZE(decon_clks_name), ctx->clks);
+	if (ret < 0)
+		return;
 
 	decon_shadow_protect(ctx, true);
 	for (win = 0; win < WINDOWS_NR; win++)
@@ -504,10 +502,6 @@ static void decon_clear_channels(struct exynos_drm_crtc *crtc)
 
 	/* TODO: wait for possible vsync */
 	msleep(50);
-
-err:
-	while (--i >= 0)
-		clk_disable_unprepare(ctx->clks[i]);
 }
 
 static enum drm_mode_status decon_mode_valid(struct exynos_drm_crtc *crtc,
@@ -638,10 +632,8 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
 static int exynos5433_decon_suspend(struct device *dev)
 {
 	struct decon_context *ctx = dev_get_drvdata(dev);
-	int i = ARRAY_SIZE(decon_clks_name);
 
-	while (--i >= 0)
-		clk_disable_unprepare(ctx->clks[i]);
+	clk_bulk_disable_unprepare(ARRAY_SIZE(decon_clks_name), ctx->clks);
 
 	return 0;
 }
@@ -649,19 +641,9 @@ static int exynos5433_decon_suspend(struct device *dev)
 static int exynos5433_decon_resume(struct device *dev)
 {
 	struct decon_context *ctx = dev_get_drvdata(dev);
-	int i, ret;
-
-	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
-		ret = clk_prepare_enable(ctx->clks[i]);
-		if (ret < 0)
-			goto err;
-	}
-
-	return 0;
+	int ret;
 
-err:
-	while (--i >= 0)
-		clk_disable_unprepare(ctx->clks[i]);
+	ret = clk_bulk_prepare_enable(ARRAY_SIZE(decon_clks_name), ctx->clks);
 
 	return ret;
 }
@@ -719,7 +701,6 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
 	struct decon_context *ctx;
 	struct resource *res;
 	int ret;
-	int i;
 
 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
@@ -732,15 +713,14 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
 	if (ctx->out_type & IFTYPE_HDMI)
 		ctx->first_win = 1;
 
-	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
-		struct clk *clk;
-
-		clk = devm_clk_get(ctx->dev, decon_clks_name[i]);
-		if (IS_ERR(clk))
-			return PTR_ERR(clk);
+	ctx->clks = devm_clk_bulk_alloc(dev, ARRAY_SIZE(decon_clks_name),
+					decon_clks_name);
+	if (IS_ERR(ctx->clks))
+		return PTR_ERR(ctx->clks);
 
-		ctx->clks[i] = clk;
-	}
+	ret = devm_clk_bulk_get(dev, ARRAY_SIZE(decon_clks_name), ctx->clks);
+	if (ret < 0)
+		return ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ctx->addr = devm_ioremap_resource(dev, res);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 4/8] drm/exynos/dsi: Use clk bulk API
       [not found]   ` <CGME20180219154459eucas1p147525b88de5d34f646aa25cb8de1f1d0@eucas1p1.samsung.com>
@ 2018-02-19 15:44     ` Maciej Purski
  2018-02-20  1:39       ` kbuild test robot
  0 siblings, 1 reply; 18+ messages in thread
From: Maciej Purski @ 2018-02-19 15:44 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, linux-arm-kernel, dri-devel,
	linux-kernel, linux-clk
  Cc: Michael Turquette, Stephen Boyd, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, David Airlie, Kukjin Kim,
	Krzysztof Kozlowski, Mauro Carvalho Chehab,
	Andrzej Pietrasiewicz, Jacek Anaszewski, Kamil Debski,
	Jeongtae Park, Andrzej Hajda, Russell King, Sylwester Nawrocki,
	Thibault Saunier, Javier Martinez Canillas, Hans Verkuil,
	Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Marek Szyprowski,
	Maciej Purski

Using bulk clk functions simplifies the driver's code. Use devm_clk_bulk
functions instead of iterating over an array of clks.

In order to achieve consistency with other drivers, define clock names
in driver's variants structures.

Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 68 +++++++++++++++------------------
 1 file changed, 30 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 7904ffa..46a8b5c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -209,11 +209,7 @@
 #define DSI_XFER_TIMEOUT_MS		100
 #define DSI_RX_FIFO_EMPTY		0x30800002
 
-#define OLD_SCLK_MIPI_CLK_NAME "pll_clk"
-
-static char *clk_names[5] = { "bus_clk", "sclk_mipi",
-	"phyclk_mipidphy0_bitclkdiv8", "phyclk_mipidphy0_rxclkesc0",
-	"sclk_rgb_vclk_to_dsim0" };
+#define DSI_MAX_CLOCKS			5
 
 enum exynos_dsi_transfer_type {
 	EXYNOS_DSI_TX,
@@ -243,6 +239,7 @@ struct exynos_dsi_driver_data {
 	unsigned int plltmr_reg;
 	unsigned int has_freqband:1;
 	unsigned int has_clklane_stop:1;
+	const char *clock_names[DSI_MAX_CLOCKS];
 	unsigned int num_clks;
 	unsigned int max_freq;
 	unsigned int wait_for_reset;
@@ -259,7 +256,7 @@ struct exynos_dsi {
 
 	void __iomem *reg_base;
 	struct phy *phy;
-	struct clk **clks;
+	struct clk_bulk_data *clks;
 	struct regulator_bulk_data supplies[2];
 	int irq;
 	int te_gpio;
@@ -453,6 +450,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = {
 	.plltmr_reg = 0x50,
 	.has_freqband = 1,
 	.has_clklane_stop = 1,
+	.clock_names = {"bus_clk", "pll_clk"},
 	.num_clks = 2,
 	.max_freq = 1000,
 	.wait_for_reset = 1,
@@ -465,6 +463,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
 	.plltmr_reg = 0x50,
 	.has_freqband = 1,
 	.has_clklane_stop = 1,
+	.clock_names = {"bus_clk", "sclk_mipi"},
 	.num_clks = 2,
 	.max_freq = 1000,
 	.wait_for_reset = 1,
@@ -475,6 +474,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
 static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
 	.reg_ofs = exynos_reg_ofs,
 	.plltmr_reg = 0x58,
+	.clock_names = {"bus_clk", "pll_clk"},
 	.num_clks = 2,
 	.max_freq = 1000,
 	.wait_for_reset = 1,
@@ -486,6 +486,10 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
 	.reg_ofs = exynos5433_reg_ofs,
 	.plltmr_reg = 0xa0,
 	.has_clklane_stop = 1,
+	.clock_names = {"bus_clk", "phyclk_mipidphy0_bitclkdiv8",
+			"phyclk_mipidphy0_rxclkesc0",
+			"sclk_rgb_vclk_to_dsim0",
+			"sclk_mipi"},
 	.num_clks = 5,
 	.max_freq = 1500,
 	.wait_for_reset = 0,
@@ -497,6 +501,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
 	.reg_ofs = exynos5433_reg_ofs,
 	.plltmr_reg = 0xa0,
 	.has_clklane_stop = 1,
+	.clock_names = {"bus_clk", "pll_clk"},
 	.num_clks = 2,
 	.max_freq = 1500,
 	.wait_for_reset = 1,
@@ -1711,7 +1716,7 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct resource *res;
 	struct exynos_dsi *dsi;
-	int ret, i;
+	int ret;
 
 	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
 	if (!dsi)
@@ -1743,26 +1748,15 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 		return -EPROBE_DEFER;
 	}
 
-	dsi->clks = devm_kzalloc(dev,
-			sizeof(*dsi->clks) * dsi->driver_data->num_clks,
-			GFP_KERNEL);
-	if (!dsi->clks)
-		return -ENOMEM;
+	dsi->clks = devm_clk_bulk_alloc(dev, dsi->driver_data->num_clks,
+					dsi->driver_data->clock_names);
+	if (IS_ERR(dsi->clks))
+		return PTR_ERR(dsi->clks);
 
-	for (i = 0; i < dsi->driver_data->num_clks; i++) {
-		dsi->clks[i] = devm_clk_get(dev, clk_names[i]);
-		if (IS_ERR(dsi->clks[i])) {
-			if (strcmp(clk_names[i], "sclk_mipi") == 0) {
-				strcpy(clk_names[i], OLD_SCLK_MIPI_CLK_NAME);
-				i--;
-				continue;
-			}
-
-			dev_info(dev, "failed to get the clock: %s\n",
-					clk_names[i]);
-			return PTR_ERR(dsi->clks[i]);
-		}
-	}
+	ret = devm_clk_bulk_get(dev, dsi->driver_data->num_clks,
+				dsi->clks);
+	if (ret < 0)
+		return ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	dsi->reg_base = devm_ioremap_resource(dev, res);
@@ -1817,7 +1811,7 @@ static int __maybe_unused exynos_dsi_suspend(struct device *dev)
 	struct drm_encoder *encoder = dev_get_drvdata(dev);
 	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
 	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
-	int ret, i;
+	int ret;
 
 	usleep_range(10000, 20000);
 
@@ -1833,8 +1827,7 @@ static int __maybe_unused exynos_dsi_suspend(struct device *dev)
 
 	phy_power_off(dsi->phy);
 
-	for (i = driver_data->num_clks - 1; i > -1; i--)
-		clk_disable_unprepare(dsi->clks[i]);
+	clk_bulk_disable_unprepare(driver_data->num_clks, dsi->clks);
 
 	ret = regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
 	if (ret < 0)
@@ -1848,7 +1841,7 @@ static int __maybe_unused exynos_dsi_resume(struct device *dev)
 	struct drm_encoder *encoder = dev_get_drvdata(dev);
 	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
 	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
-	int ret, i;
+	int ret;
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
 	if (ret < 0) {
@@ -1856,23 +1849,22 @@ static int __maybe_unused exynos_dsi_resume(struct device *dev)
 		return ret;
 	}
 
-	for (i = 0; i < driver_data->num_clks; i++) {
-		ret = clk_prepare_enable(dsi->clks[i]);
-		if (ret < 0)
-			goto err_clk;
-	}
+	ret = clk_bulk_prepare_enable(driver_data->num_clks, dsi->clks);
+	if (ret < 0)
+		goto err_clk;
 
 	ret = phy_power_on(dsi->phy);
 	if (ret < 0) {
 		dev_err(dsi->dev, "cannot enable phy %d\n", ret);
-		goto err_clk;
+		goto err_phy;
 	}
 
 	return 0;
 
+err_phy:
+	clk_bulk_disable_unprepare(driver_data->num_clks, dsi->clks);
+
 err_clk:
-	while (--i > -1)
-		clk_disable_unprepare(dsi->clks[i]);
 	regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
 
 	return ret;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 5/8] drm/exynos: mic: Use clk bulk API
       [not found]   ` <CGME20180219154500eucas1p25e9f3bf44901cb2bbe9720cdc5bdd855@eucas1p2.samsung.com>
@ 2018-02-19 15:44     ` Maciej Purski
  0 siblings, 0 replies; 18+ messages in thread
From: Maciej Purski @ 2018-02-19 15:44 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, linux-arm-kernel, dri-devel,
	linux-kernel, linux-clk
  Cc: Michael Turquette, Stephen Boyd, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, David Airlie, Kukjin Kim,
	Krzysztof Kozlowski, Mauro Carvalho Chehab,
	Andrzej Pietrasiewicz, Jacek Anaszewski, Kamil Debski,
	Jeongtae Park, Andrzej Hajda, Russell King, Sylwester Nawrocki,
	Thibault Saunier, Javier Martinez Canillas, Hans Verkuil,
	Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Marek Szyprowski,
	Maciej Purski

Using bulk clk functions simplifies the driver's code. Use devm_clk_bulk
functions instead of iterating over an array of clks.

Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_mic.c | 41 +++++++++++----------------------
 1 file changed, 14 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index 2174814..276558a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -88,7 +88,7 @@
 
 #define MIC_BS_SIZE_2D(x)	((x) & 0x3fff)
 
-static char *clk_names[] = { "pclk_mic0", "sclk_rgb_vclk_to_mic0" };
+static const char *const clk_names[] = { "pclk_mic0", "sclk_rgb_vclk_to_mic0" };
 #define NUM_CLKS		ARRAY_SIZE(clk_names)
 static DEFINE_MUTEX(mic_mutex);
 
@@ -96,7 +96,7 @@ struct exynos_mic {
 	struct device *dev;
 	void __iomem *reg;
 	struct regmap *sysreg;
-	struct clk *clks[NUM_CLKS];
+	struct clk_bulk_data *clks;
 
 	bool i80_mode;
 	struct videomode vm;
@@ -338,10 +338,8 @@ static const struct component_ops exynos_mic_component_ops = {
 static int exynos_mic_suspend(struct device *dev)
 {
 	struct exynos_mic *mic = dev_get_drvdata(dev);
-	int i;
 
-	for (i = NUM_CLKS - 1; i > -1; i--)
-		clk_disable_unprepare(mic->clks[i]);
+	clk_bulk_disable_unprepare(NUM_CLKS, mic->clks);
 
 	return 0;
 }
@@ -349,19 +347,8 @@ static int exynos_mic_suspend(struct device *dev)
 static int exynos_mic_resume(struct device *dev)
 {
 	struct exynos_mic *mic = dev_get_drvdata(dev);
-	int ret, i;
-
-	for (i = 0; i < NUM_CLKS; i++) {
-		ret = clk_prepare_enable(mic->clks[i]);
-		if (ret < 0) {
-			DRM_ERROR("Failed to enable clock (%s)\n",
-							clk_names[i]);
-			while (--i > -1)
-				clk_disable_unprepare(mic->clks[i]);
-			return ret;
-		}
-	}
-	return 0;
+
+	return clk_bulk_prepare_enable(NUM_CLKS, mic->clks);
 }
 #endif
 
@@ -374,7 +361,7 @@ static int exynos_mic_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct exynos_mic *mic;
 	struct resource res;
-	int ret, i;
+	int ret;
 
 	mic = devm_kzalloc(dev, sizeof(*mic), GFP_KERNEL);
 	if (!mic) {
@@ -405,16 +392,16 @@ static int exynos_mic_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	for (i = 0; i < NUM_CLKS; i++) {
-		mic->clks[i] = devm_clk_get(dev, clk_names[i]);
-		if (IS_ERR(mic->clks[i])) {
-			DRM_ERROR("mic: Failed to get clock (%s)\n",
-								clk_names[i]);
-			ret = PTR_ERR(mic->clks[i]);
-			goto err;
-		}
+	mic->clks = devm_clk_bulk_alloc(dev, NUM_CLKS, clk_names);
+	if (IS_ERR(mic->clks)) {
+		ret = PTR_ERR(mic->clks);
+		goto err;
 	}
 
+	ret = devm_clk_bulk_get(dev, NUM_CLKS, mic->clks);
+	if (ret < 0)
+		goto err;
+
 	platform_set_drvdata(pdev, mic);
 
 	mic->bridge.funcs = &mic_bridge_funcs;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 6/8] drm/exynos/hdmi: Use clk bulk API
       [not found]   ` <CGME20180219154501eucas1p1e16a883d2eb0c8a99bafce5d71656066@eucas1p1.samsung.com>
@ 2018-02-19 15:44     ` Maciej Purski
  0 siblings, 0 replies; 18+ messages in thread
From: Maciej Purski @ 2018-02-19 15:44 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, linux-arm-kernel, dri-devel,
	linux-kernel, linux-clk
  Cc: Michael Turquette, Stephen Boyd, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, David Airlie, Kukjin Kim,
	Krzysztof Kozlowski, Mauro Carvalho Chehab,
	Andrzej Pietrasiewicz, Jacek Anaszewski, Kamil Debski,
	Jeongtae Park, Andrzej Hajda, Russell King, Sylwester Nawrocki,
	Thibault Saunier, Javier Martinez Canillas, Hans Verkuil,
	Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Marek Szyprowski,
	Maciej Purski

Using bulk clk functions simplifies the driver's code. Use devm_clk_bulk
functions instead of iterating over an array of clks.

Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 97 ++++++++++--------------------------
 1 file changed, 27 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index a4b75a4..6c208f7 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -136,8 +136,8 @@ struct hdmi_context {
 	int				irq;
 	struct regmap			*pmureg;
 	struct regmap			*sysreg;
-	struct clk			**clk_gates;
-	struct clk			**clk_muxes;
+	struct clk_bulk_data		*clk_gates;
+	struct clk_bulk_data		*clk_muxes;
 	struct regulator_bulk_data	regul_bulk[ARRAY_SIZE(supply)];
 	struct regulator		*reg_hdmi_en;
 	struct exynos_drm_clk		phy_clk;
@@ -739,43 +739,16 @@ static int hdmiphy_reg_write_buf(struct hdmi_context *hdata,
 	}
 }
 
-static int hdmi_clk_enable_gates(struct hdmi_context *hdata)
-{
-	int i, ret;
-
-	for (i = 0; i < hdata->drv_data->clk_gates.count; ++i) {
-		ret = clk_prepare_enable(hdata->clk_gates[i]);
-		if (!ret)
-			continue;
-
-		dev_err(hdata->dev, "Cannot enable clock '%s', %d\n",
-			hdata->drv_data->clk_gates.data[i], ret);
-		while (i--)
-			clk_disable_unprepare(hdata->clk_gates[i]);
-		return ret;
-	}
-
-	return 0;
-}
-
-static void hdmi_clk_disable_gates(struct hdmi_context *hdata)
-{
-	int i = hdata->drv_data->clk_gates.count;
-
-	while (i--)
-		clk_disable_unprepare(hdata->clk_gates[i]);
-}
-
 static int hdmi_clk_set_parents(struct hdmi_context *hdata, bool to_phy)
 {
 	struct device *dev = hdata->dev;
 	int ret = 0;
+	struct clk_bulk_data *clk_muxes = hdata->clk_muxes;
 	int i;
 
 	for (i = 0; i < hdata->drv_data->clk_muxes.count; i += 3) {
-		struct clk **c = &hdata->clk_muxes[i];
-
-		ret = clk_set_parent(c[2], c[to_phy]);
+		ret = clk_set_parent(clk_muxes[i + 2].clk,
+				     clk_muxes[i + to_phy].clk);
 		if (!ret)
 			continue;
 
@@ -1655,54 +1628,36 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
-static int hdmi_clks_get(struct hdmi_context *hdata,
-			 const struct string_array_spec *names,
-			 struct clk **clks)
+static struct clk_bulk_data *hdmi_clks_alloc_get(struct hdmi_context *hdata,
+					const struct string_array_spec *names)
 {
-	struct device *dev = hdata->dev;
-	int i;
-
-	for (i = 0; i < names->count; ++i) {
-		struct clk *clk = devm_clk_get(dev, names->data[i]);
-
-		if (IS_ERR(clk)) {
-			int ret = PTR_ERR(clk);
+	struct clk_bulk_data *ptr;
+	int ret;
 
-			dev_err(dev, "Cannot get clock %s, %d\n",
-				names->data[i], ret);
+	ptr = devm_clk_bulk_alloc(hdata->dev, names->count, names->data);
+	if (IS_ERR(ptr))
+		return ptr;
 
-			return ret;
-		}
-
-		clks[i] = clk;
-	}
+	ret = devm_clk_bulk_get(hdata->dev, names->count, ptr);
+	if (ret < 0)
+		return ERR_PTR(ret);
 
-	return 0;
+	return ptr;
 }
 
 static int hdmi_clk_init(struct hdmi_context *hdata)
 {
 	const struct hdmi_driver_data *drv_data = hdata->drv_data;
-	int count = drv_data->clk_gates.count + drv_data->clk_muxes.count;
-	struct device *dev = hdata->dev;
-	struct clk **clks;
-	int ret;
 
-	if (!count)
-		return 0;
-
-	clks = devm_kzalloc(dev, sizeof(*clks) * count, GFP_KERNEL);
-	if (!clks)
-		return -ENOMEM;
+	hdata->clk_muxes = hdmi_clks_alloc_get(hdata, &drv_data->clk_muxes);
+	if (IS_ERR(hdata->clk_muxes))
+		return PTR_ERR(hdata->clk_muxes);
 
-	hdata->clk_gates = clks;
-	hdata->clk_muxes = clks + drv_data->clk_gates.count;
+	hdata->clk_gates = hdmi_clks_alloc_get(hdata, &drv_data->clk_gates);
+	if (IS_ERR(hdata->clk_gates))
+		return PTR_ERR(hdata->clk_gates);
 
-	ret = hdmi_clks_get(hdata, &drv_data->clk_gates, hdata->clk_gates);
-	if (ret)
-		return ret;
-
-	return hdmi_clks_get(hdata, &drv_data->clk_muxes, hdata->clk_muxes);
+	return 0;
 }
 
 
@@ -2073,7 +2028,8 @@ static int __maybe_unused exynos_hdmi_suspend(struct device *dev)
 {
 	struct hdmi_context *hdata = dev_get_drvdata(dev);
 
-	hdmi_clk_disable_gates(hdata);
+	clk_bulk_disable_unprepare(hdata->drv_data->clk_gates.count,
+				   hdata->clk_gates);
 
 	return 0;
 }
@@ -2083,7 +2039,8 @@ static int __maybe_unused exynos_hdmi_resume(struct device *dev)
 	struct hdmi_context *hdata = dev_get_drvdata(dev);
 	int ret;
 
-	ret = hdmi_clk_enable_gates(hdata);
+	ret = clk_bulk_prepare_enable(hdata->drv_data->clk_gates.count,
+				      hdata->clk_gates);
 	if (ret < 0)
 		return ret;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 7/8] [media] exynos-gsc: Use clk bulk API
       [not found]   ` <CGME20180219154502eucas1p20e8daf3edc6737817f8d62db5a2099f2@eucas1p2.samsung.com>
@ 2018-02-19 15:44     ` Maciej Purski
  2018-02-19 22:38       ` kbuild test robot
  0 siblings, 1 reply; 18+ messages in thread
From: Maciej Purski @ 2018-02-19 15:44 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, linux-arm-kernel, dri-devel,
	linux-kernel, linux-clk
  Cc: Michael Turquette, Stephen Boyd, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, David Airlie, Kukjin Kim,
	Krzysztof Kozlowski, Mauro Carvalho Chehab,
	Andrzej Pietrasiewicz, Jacek Anaszewski, Kamil Debski,
	Jeongtae Park, Andrzej Hajda, Russell King, Sylwester Nawrocki,
	Thibault Saunier, Javier Martinez Canillas, Hans Verkuil,
	Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Marek Szyprowski,
	Maciej Purski

Using bulk clk functions simplifies the driver's code. Use devm_clk_bulk
functions instead of iterating over an array of clks.

Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
 drivers/media/platform/exynos-gsc/gsc-core.c | 55 ++++++++++------------------
 drivers/media/platform/exynos-gsc/gsc-core.h |  2 +-
 2 files changed, 20 insertions(+), 37 deletions(-)

diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
index 17854a3..fa7e993 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.c
+++ b/drivers/media/platform/exynos-gsc/gsc-core.c
@@ -1149,7 +1149,6 @@ static int gsc_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	const struct gsc_driverdata *drv_data = of_device_get_match_data(dev);
 	int ret;
-	int i;
 
 	gsc = devm_kzalloc(dev, sizeof(struct gsc_dev), GFP_KERNEL);
 	if (!gsc)
@@ -1187,25 +1186,19 @@ static int gsc_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
-	for (i = 0; i < gsc->num_clocks; i++) {
-		gsc->clock[i] = devm_clk_get(dev, drv_data->clk_names[i]);
-		if (IS_ERR(gsc->clock[i])) {
-			dev_err(dev, "failed to get clock: %s\n",
-				drv_data->clk_names[i]);
-			return PTR_ERR(gsc->clock[i]);
-		}
-	}
+	gsc->clocks = devm_clk_bulk_alloc(dev, gsc->num_clocks,
+					  drv_data->clk_names);
+	if (IS_ERR(gsc->clocks))
+		return PTR_ERR(gsc->clocks);
 
-	for (i = 0; i < gsc->num_clocks; i++) {
-		ret = clk_prepare_enable(gsc->clock[i]);
-		if (ret) {
-			dev_err(dev, "clock prepare failed for clock: %s\n",
-				drv_data->clk_names[i]);
-			while (--i >= 0)
-				clk_disable_unprepare(gsc->clock[i]);
-			return ret;
-		}
-	}
+	ret = devm_clk_bulk_get(dev, gsc->num_clocks,
+				gsc->clocks);
+	if (ret)
+		return ret;
+
+	ret = clk_bulk_prepare_enable(gsc->num_clocks, gsc->clocks);
+	if (ret)
+		return ret;
 
 	ret = devm_request_irq(dev, res->start, gsc_irq_handler,
 				0, pdev->name, gsc);
@@ -1239,15 +1232,14 @@ static int gsc_probe(struct platform_device *pdev)
 err_v4l2:
 	v4l2_device_unregister(&gsc->v4l2_dev);
 err_clk:
-	for (i = gsc->num_clocks - 1; i >= 0; i--)
-		clk_disable_unprepare(gsc->clock[i]);
+	clk_bulk_disable_unprepare(gsc->num_clocks, gsc->clocks);
+
 	return ret;
 }
 
 static int gsc_remove(struct platform_device *pdev)
 {
 	struct gsc_dev *gsc = platform_get_drvdata(pdev);
-	int i;
 
 	pm_runtime_get_sync(&pdev->dev);
 
@@ -1255,8 +1247,7 @@ static int gsc_remove(struct platform_device *pdev)
 	v4l2_device_unregister(&gsc->v4l2_dev);
 
 	vb2_dma_contig_clear_max_seg_size(&pdev->dev);
-	for (i = 0; i < gsc->num_clocks; i++)
-		clk_disable_unprepare(gsc->clock[i]);
+	clk_bulk_disable_unprepare(gsc->num_clocks, gsc->clocks);
 
 	pm_runtime_put_noidle(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
@@ -1307,18 +1298,12 @@ static int gsc_runtime_resume(struct device *dev)
 {
 	struct gsc_dev *gsc = dev_get_drvdata(dev);
 	int ret = 0;
-	int i;
 
 	pr_debug("gsc%d: state: 0x%lx\n", gsc->id, gsc->state);
 
-	for (i = 0; i < gsc->num_clocks; i++) {
-		ret = clk_prepare_enable(gsc->clock[i]);
-		if (ret) {
-			while (--i >= 0)
-				clk_disable_unprepare(gsc->clock[i]);
-			return ret;
-		}
-	}
+	ret = clk_bulk_prepare_enable(gsc->num_clocks, gsc->clocks);
+	if (ret)
+		return ret;
 
 	gsc_hw_set_sw_reset(gsc);
 	gsc_wait_reset(gsc);
@@ -1331,14 +1316,12 @@ static int gsc_runtime_suspend(struct device *dev)
 {
 	struct gsc_dev *gsc = dev_get_drvdata(dev);
 	int ret = 0;
-	int i;
 
 	ret = gsc_m2m_suspend(gsc);
 	if (ret)
 		return ret;
 
-	for (i = gsc->num_clocks - 1; i >= 0; i--)
-		clk_disable_unprepare(gsc->clock[i]);
+	clk_bulk_disable_unprepare(gsc->num_clocks, gsc->clocks);
 
 	pr_debug("gsc%d: state: 0x%lx\n", gsc->id, gsc->state);
 	return ret;
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
index 715d9c9d..08ff7b9 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.h
+++ b/drivers/media/platform/exynos-gsc/gsc-core.h
@@ -334,7 +334,7 @@ struct gsc_dev {
 	struct gsc_variant		*variant;
 	u16				id;
 	int				num_clocks;
-	struct clk			*clock[GSC_MAX_CLOCKS];
+	struct clk_bulk_data		*clocks;
 	void __iomem			*regs;
 	wait_queue_head_t		irq_queue;
 	struct gsc_m2m_device		m2m;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 8/8] [media] s5p-mfc: Use clk bulk API
       [not found]   ` <CGME20180219154503eucas1p1c8893411994bd1152d0ce5b386118416@eucas1p1.samsung.com>
@ 2018-02-19 15:44     ` Maciej Purski
  2018-02-20  1:56       ` kbuild test robot
  0 siblings, 1 reply; 18+ messages in thread
From: Maciej Purski @ 2018-02-19 15:44 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, linux-arm-kernel, dri-devel,
	linux-kernel, linux-clk
  Cc: Michael Turquette, Stephen Boyd, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, David Airlie, Kukjin Kim,
	Krzysztof Kozlowski, Mauro Carvalho Chehab,
	Andrzej Pietrasiewicz, Jacek Anaszewski, Kamil Debski,
	Jeongtae Park, Andrzej Hajda, Russell King, Sylwester Nawrocki,
	Thibault Saunier, Javier Martinez Canillas, Hans Verkuil,
	Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Marek Szyprowski,
	Maciej Purski

Using bulk clk functions simplifies the driver's code. Use devm_clk_bulk
functions instead of iterating over an array of clks.

Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h |  6 ++--
 drivers/media/platform/s5p-mfc/s5p_mfc_pm.c     | 41 +++++++++----------------
 2 files changed, 18 insertions(+), 29 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 76119a8..da3f0b3 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -192,9 +192,9 @@ struct s5p_mfc_buf {
  * struct s5p_mfc_pm - power management data structure
  */
 struct s5p_mfc_pm {
-	struct clk	*clock_gate;
-	const char * const *clk_names;
-	struct clk	*clocks[MFC_MAX_CLOCKS];
+	struct clk		*clock_gate;
+	const char * const	*clk_names;
+	struct clk_bulk_data	*clocks;
 	int		num_clocks;
 	bool		use_clock_gating;
 
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index eb85ced..857f6ea 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -24,7 +24,7 @@ static atomic_t clk_ref;
 
 int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
 {
-	int i;
+	int ret;
 
 	pm = &dev->pm;
 	p_dev = dev;
@@ -35,17 +35,17 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
 	pm->clock_gate = NULL;
 
 	/* clock control */
-	for (i = 0; i < pm->num_clocks; i++) {
-		pm->clocks[i] = devm_clk_get(pm->device, pm->clk_names[i]);
-		if (IS_ERR(pm->clocks[i])) {
-			mfc_err("Failed to get clock: %s\n",
-				pm->clk_names[i]);
-			return PTR_ERR(pm->clocks[i]);
-		}
-	}
+	pm->clocks = devm_clk_bulk_alloc(pm->device, pm->num_clocks,
+					 pm->clk_names);
+	if (IS_ERR(pm->clocks))
+		return PTR_ERR(pm->clocks);
+
+	ret = devm_clk_bulk_get(pm->device, pm->num_clocks, pm->clocks);
+	if (ret < 0)
+		return ret;
 
 	if (dev->variant->use_clock_gating)
-		pm->clock_gate = pm->clocks[0];
+		pm->clock_gate = pm->clocks[0].clk;
 
 	pm_runtime_enable(pm->device);
 	atomic_set(&clk_ref, 0);
@@ -75,43 +75,32 @@ void s5p_mfc_clock_off(void)
 
 int s5p_mfc_power_on(void)
 {
-	int i, ret = 0;
+	int ret = 0;
 
 	ret = pm_runtime_get_sync(pm->device);
 	if (ret < 0)
 		return ret;
 
 	/* clock control */
-	for (i = 0; i < pm->num_clocks; i++) {
-		ret = clk_prepare_enable(pm->clocks[i]);
-		if (ret < 0) {
-			mfc_err("clock prepare failed for clock: %s\n",
-				pm->clk_names[i]);
-			i++;
-			goto err;
-		}
-	}
+	ret = clk_bulk_prepare_enable(pm->num_clocks, pm->clocks);
+	if (ret < 0)
+		goto err;
 
 	/* prepare for software clock gating */
 	clk_disable(pm->clock_gate);
 
 	return 0;
 err:
-	while (--i > 0)
-		clk_disable_unprepare(pm->clocks[i]);
 	pm_runtime_put(pm->device);
 	return ret;
 }
 
 int s5p_mfc_power_off(void)
 {
-	int i;
-
 	/* finish software clock gating */
 	clk_enable(pm->clock_gate);
 
-	for (i = 0; i < pm->num_clocks; i++)
-		clk_disable_unprepare(pm->clocks[i]);
+	clk_bulk_disable_unprepare(pm->num_clocks, pm->clocks);
 
 	return pm_runtime_put_sync(pm->device);
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/8] clk: Add clk_bulk_alloc functions
  2018-02-19 15:43     ` [PATCH 1/8] clk: Add clk_bulk_alloc functions Maciej Purski
@ 2018-02-19 16:29       ` Robin Murphy
  2018-02-20  9:36         ` Marek Szyprowski
  2018-02-19 18:22       ` Emil Velikov
  1 sibling, 1 reply; 18+ messages in thread
From: Robin Murphy @ 2018-02-19 16:29 UTC (permalink / raw)
  To: Maciej Purski, linux-media, linux-samsung-soc, linux-arm-kernel,
	dri-devel, linux-kernel, linux-clk
  Cc: David Airlie, Michael Turquette, Kamil Debski, Andrzej Hajda,
	Sylwester Nawrocki, Marek Szyprowski, Thibault Saunier,
	Joonyoung Shim, Russell King, Krzysztof Kozlowski,
	Javier Martinez Canillas, Kukjin Kim, Hoegeun Kwon,
	Bartlomiej Zolnierkiewicz, Inki Dae, Jeongtae Park,
	Jacek Anaszewski, Andrzej Pietrasiewicz, Mauro Carvalho Chehab,
	Stephen Boyd, Seung-Woo Kim, Hans Verkuil, Kyungmin Park

Hi Maciej,

On 19/02/18 15:43, Maciej Purski wrote:
> When a driver is going to use clk_bulk_get() function, it has to
> initialize an array of clk_bulk_data, by filling its id fields.
> 
> Add a new function to the core, which dynamically allocates
> clk_bulk_data array and fills its id fields. Add clk_bulk_free()
> function, which frees the array allocated by clk_bulk_alloc() function.
> Add a managed version of clk_bulk_alloc().

Seeing how every subsequent patch ends up with the roughly this same stanza:

	x = devm_clk_bulk_alloc(dev, num, names);
	if (IS_ERR(x)
		return PTR_ERR(x);
	ret = devm_clk_bulk_get(dev, x, num);

I wonder if it might be better to simply implement:

	int devm_clk_bulk_alloc_get(dev, &x, num, names)

that does the whole lot in one go, and let drivers that want to do more 
fiddly things continue to open-code the allocation.

But perhaps that's an abstraction too far... I'm not all that familiar 
with the lie of the land here.

> Signed-off-by: Maciej Purski <m.purski@samsung.com>
> ---
>   drivers/clk/clk-bulk.c   | 16 ++++++++++++
>   drivers/clk/clk-devres.c | 37 +++++++++++++++++++++++++---
>   include/linux/clk.h      | 64 ++++++++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 113 insertions(+), 4 deletions(-)
> 

[...]
> @@ -598,6 +645,23 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id);
>   
>   #else /* !CONFIG_HAVE_CLK */
>   
> +static inline struct clk_bulk_data *clk_bulk_alloc(int num_clks,
> +						   const char **clk_ids)
> +{
> +	return NULL;

Either way, is it intentional not returning an ERR_PTR() value in this 
case? Since NULL will pass an IS_ERR() check, it seems a bit fragile for 
an allocation call to apparently succeed when the whole API is 
configured out (and I believe introducing new uses of IS_ERR_OR_NULL() 
is in general strongly discouraged.)

Robin.

> +}
> +
> +static inline struct clk_bulk_data *devm_clk_bulk_alloc(struct device *dev,
> +							int num_clks,
> +							const char **clk_ids)
> +{
> +	return NULL;
> +}
> +
> +static inline void clk_bulk_free(struct clk_bulk_data *clks)
> +{
> +}
> +
>   static inline struct clk *clk_get(struct device *dev, const char *id)
>   {
>   	return NULL;
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/8] clk: Add clk_bulk_alloc functions
  2018-02-19 15:43     ` [PATCH 1/8] clk: Add clk_bulk_alloc functions Maciej Purski
  2018-02-19 16:29       ` Robin Murphy
@ 2018-02-19 18:22       ` Emil Velikov
  1 sibling, 0 replies; 18+ messages in thread
From: Emil Velikov @ 2018-02-19 18:22 UTC (permalink / raw)
  To: Maciej Purski
  Cc: linux-media, moderated list:ARM/S5P EXYNOS AR...,
	LAKML, ML dri-devel, Linux-Kernel@Vger. Kernel. Org, linux-clk,
	David Airlie, Michael Turquette, Kamil Debski,
	Sylwester Nawrocki, Marek Szyprowski, Thibault Saunier,
	Russell King, Krzysztof Kozlowski, Javier Martinez Canillas,
	Kukjin Kim, Hoegeun Kwon, Bartlomiej Zolnierkiewicz,
	Jeongtae Park, Jacek Anaszewski, Andrzej Pietrasiewicz,
	Mauro Carvalho Chehab, Stephen Boyd, Seung-Woo Kim, Hans Verkuil,
	Kyungmin Park

HI Maciej,

Just sharing a couple of fly-by ideas - please don't read too much into them.

On 19 February 2018 at 15:43, Maciej Purski <m.purski@samsung.com> wrote:
> When a driver is going to use clk_bulk_get() function, it has to
> initialize an array of clk_bulk_data, by filling its id fields.
>
> Add a new function to the core, which dynamically allocates
> clk_bulk_data array and fills its id fields. Add clk_bulk_free()
> function, which frees the array allocated by clk_bulk_alloc() function.
> Add a managed version of clk_bulk_alloc().
>
Most places use a small fixed number of struct clk pointers.
Using devres + kalloc to allocate 1-4 pointers feels a bit strange.

Quick grep shows over 150 instances that could be updated to use the new API.
Adding a cocci script to simplify the transition would be a good idea.

> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -15,6 +15,7 @@
>  #include <linux/err.h>
>  #include <linux/kernel.h>
>  #include <linux/notifier.h>
> +#include <linux/slab.h>
>
The extra header declaration should not be needed. One should be able
to forward declare any undefined structs.

HTH
Emil

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 7/8] [media] exynos-gsc: Use clk bulk API
  2018-02-19 15:44     ` [PATCH 7/8] [media] exynos-gsc: " Maciej Purski
@ 2018-02-19 22:38       ` kbuild test robot
  0 siblings, 0 replies; 18+ messages in thread
From: kbuild test robot @ 2018-02-19 22:38 UTC (permalink / raw)
  To: Maciej Purski
  Cc: kbuild-all, linux-media, linux-samsung-soc, linux-arm-kernel,
	dri-devel, linux-kernel, linux-clk, David Airlie,
	Michael Turquette, Kamil Debski, Maciej Purski,
	Sylwester Nawrocki, Marek Szyprowski, Thibault Saunier,
	Russell King, Krzysztof Kozlowski, Javier Martinez Canillas,
	Kukjin Kim, Hoegeun Kwon, Bartlomiej Zolnierkiewicz,
	Jeongtae Park, Jacek Anaszewski, Andrzej Pietrasiewicz,
	Mauro Carvalho Chehab, Stephen Boyd, Seung-Woo Kim, Hans Verkuil,
	Kyungmin Park

[-- Attachment #1: Type: text/plain, Size: 4510 bytes --]

Hi Maciej,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v4.16-rc2 next-20180219]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Maciej-Purski/Use-clk-bulk-API-in-exynos5433-drivers/20180220-054431
base:   git://linuxtv.org/media_tree.git master
config: sparc64-allmodconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sparc64 

All warnings (new ones prefixed by >>):

   drivers/media/platform/exynos-gsc/gsc-core.c: In function 'gsc_probe':
>> drivers/media/platform/exynos-gsc/gsc-core.c:1190:8: warning: passing argument 3 of 'devm_clk_bulk_alloc' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
           drv_data->clk_names);
           ^~~~~~~~
   In file included from drivers/media/platform/exynos-gsc/gsc-core.c:25:0:
   include/linux/clk.h:654:37: note: expected 'const char **' but argument is of type 'const char * const*'
    static inline struct clk_bulk_data *devm_clk_bulk_alloc(struct device *dev,
                                        ^~~~~~~~~~~~~~~~~~~

vim +1190 drivers/media/platform/exynos-gsc/gsc-core.c

  1144	
  1145	static int gsc_probe(struct platform_device *pdev)
  1146	{
  1147		struct gsc_dev *gsc;
  1148		struct resource *res;
  1149		struct device *dev = &pdev->dev;
  1150		const struct gsc_driverdata *drv_data = of_device_get_match_data(dev);
  1151		int ret;
  1152	
  1153		gsc = devm_kzalloc(dev, sizeof(struct gsc_dev), GFP_KERNEL);
  1154		if (!gsc)
  1155			return -ENOMEM;
  1156	
  1157		ret = of_alias_get_id(pdev->dev.of_node, "gsc");
  1158		if (ret < 0)
  1159			return ret;
  1160	
  1161		if (drv_data == &gsc_v_100_drvdata)
  1162			dev_info(dev, "compatible 'exynos5-gsc' is deprecated\n");
  1163	
  1164		gsc->id = ret;
  1165		if (gsc->id >= drv_data->num_entities) {
  1166			dev_err(dev, "Invalid platform device id: %d\n", gsc->id);
  1167			return -EINVAL;
  1168		}
  1169	
  1170		gsc->num_clocks = drv_data->num_clocks;
  1171		gsc->variant = drv_data->variant[gsc->id];
  1172		gsc->pdev = pdev;
  1173	
  1174		init_waitqueue_head(&gsc->irq_queue);
  1175		spin_lock_init(&gsc->slock);
  1176		mutex_init(&gsc->lock);
  1177	
  1178		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  1179		gsc->regs = devm_ioremap_resource(dev, res);
  1180		if (IS_ERR(gsc->regs))
  1181			return PTR_ERR(gsc->regs);
  1182	
  1183		res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  1184		if (!res) {
  1185			dev_err(dev, "failed to get IRQ resource\n");
  1186			return -ENXIO;
  1187		}
  1188	
  1189		gsc->clocks = devm_clk_bulk_alloc(dev, gsc->num_clocks,
> 1190						  drv_data->clk_names);
  1191		if (IS_ERR(gsc->clocks))
  1192			return PTR_ERR(gsc->clocks);
  1193	
  1194		ret = devm_clk_bulk_get(dev, gsc->num_clocks,
  1195					gsc->clocks);
  1196		if (ret)
  1197			return ret;
  1198	
  1199		ret = clk_bulk_prepare_enable(gsc->num_clocks, gsc->clocks);
  1200		if (ret)
  1201			return ret;
  1202	
  1203		ret = devm_request_irq(dev, res->start, gsc_irq_handler,
  1204					0, pdev->name, gsc);
  1205		if (ret) {
  1206			dev_err(dev, "failed to install irq (%d)\n", ret);
  1207			goto err_clk;
  1208		}
  1209	
  1210		ret = v4l2_device_register(dev, &gsc->v4l2_dev);
  1211		if (ret)
  1212			goto err_clk;
  1213	
  1214		ret = gsc_register_m2m_device(gsc);
  1215		if (ret)
  1216			goto err_v4l2;
  1217	
  1218		platform_set_drvdata(pdev, gsc);
  1219	
  1220		gsc_hw_set_sw_reset(gsc);
  1221		gsc_wait_reset(gsc);
  1222	
  1223		vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
  1224	
  1225		dev_dbg(dev, "gsc-%d registered successfully\n", gsc->id);
  1226	
  1227		pm_runtime_set_active(dev);
  1228		pm_runtime_enable(dev);
  1229	
  1230		return 0;
  1231	
  1232	err_v4l2:
  1233		v4l2_device_unregister(&gsc->v4l2_dev);
  1234	err_clk:
  1235		clk_bulk_disable_unprepare(gsc->num_clocks, gsc->clocks);
  1236	
  1237		return ret;
  1238	}
  1239	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 53401 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/8] media: s5p-jpeg: Use bulk clk API
  2018-02-19 15:44     ` [PATCH 2/8] media: s5p-jpeg: Use bulk clk API Maciej Purski
@ 2018-02-20  0:22       ` kbuild test robot
  0 siblings, 0 replies; 18+ messages in thread
From: kbuild test robot @ 2018-02-20  0:22 UTC (permalink / raw)
  To: Maciej Purski
  Cc: kbuild-all, linux-media, linux-samsung-soc, linux-arm-kernel,
	dri-devel, linux-kernel, linux-clk, David Airlie,
	Michael Turquette, Kamil Debski, Maciej Purski,
	Sylwester Nawrocki, Marek Szyprowski, Thibault Saunier,
	Russell King, Krzysztof Kozlowski, Javier Martinez Canillas,
	Kukjin Kim, Hoegeun Kwon, Bartlomiej Zolnierkiewicz,
	Jeongtae Park, Jacek Anaszewski, Andrzej Pietrasiewicz,
	Mauro Carvalho Chehab, Stephen Boyd, Seung-Woo Kim, Hans Verkuil,
	Kyungmin Park

[-- Attachment #1: Type: text/plain, Size: 1064 bytes --]

Hi Maciej,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.16-rc2 next-20180219]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Maciej-Purski/Use-clk-bulk-API-in-exynos5433-drivers/20180220-054431
base:   git://linuxtv.org/media_tree.git master
config: arm-multi_v7_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All errors (new ones prefixed by >>):

>> ERROR: "devm_clk_bulk_alloc" [drivers/media/platform/s5p-jpeg/s5p-jpeg.ko] undefined!

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 42953 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] drm/exynos/dsi: Use clk bulk API
  2018-02-19 15:44     ` [PATCH 4/8] drm/exynos/dsi: " Maciej Purski
@ 2018-02-20  1:39       ` kbuild test robot
  0 siblings, 0 replies; 18+ messages in thread
From: kbuild test robot @ 2018-02-20  1:39 UTC (permalink / raw)
  To: Maciej Purski
  Cc: kbuild-all, linux-media, linux-samsung-soc, linux-arm-kernel,
	dri-devel, linux-kernel, linux-clk, David Airlie,
	Michael Turquette, Kamil Debski, Maciej Purski,
	Sylwester Nawrocki, Marek Szyprowski, Thibault Saunier,
	Russell King, Krzysztof Kozlowski, Javier Martinez Canillas,
	Kukjin Kim, Hoegeun Kwon, Bartlomiej Zolnierkiewicz,
	Jeongtae Park, Jacek Anaszewski, Andrzej Pietrasiewicz,
	Mauro Carvalho Chehab, Stephen Boyd, Seung-Woo Kim, Hans Verkuil,
	Kyungmin Park

[-- Attachment #1: Type: text/plain, Size: 1145 bytes --]

Hi Maciej,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.16-rc2 next-20180219]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Maciej-Purski/Use-clk-bulk-API-in-exynos5433-drivers/20180220-054431
base:   git://linuxtv.org/media_tree.git master
config: arm-multi_v7_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   ERROR: "devm_clk_bulk_alloc" [drivers/media/platform/s5p-jpeg/s5p-jpeg.ko] undefined!
>> ERROR: "devm_clk_bulk_alloc" [drivers/gpu/drm/exynos/exynosdrm.ko] undefined!

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 42953 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 8/8] [media] s5p-mfc: Use clk bulk API
  2018-02-19 15:44     ` [PATCH 8/8] [media] s5p-mfc: " Maciej Purski
@ 2018-02-20  1:56       ` kbuild test robot
  0 siblings, 0 replies; 18+ messages in thread
From: kbuild test robot @ 2018-02-20  1:56 UTC (permalink / raw)
  To: Maciej Purski
  Cc: kbuild-all, linux-media, linux-samsung-soc, linux-arm-kernel,
	dri-devel, linux-kernel, linux-clk, David Airlie,
	Michael Turquette, Kamil Debski, Maciej Purski,
	Sylwester Nawrocki, Marek Szyprowski, Thibault Saunier,
	Russell King, Krzysztof Kozlowski, Javier Martinez Canillas,
	Kukjin Kim, Hoegeun Kwon, Bartlomiej Zolnierkiewicz,
	Jeongtae Park, Jacek Anaszewski, Andrzej Pietrasiewicz,
	Mauro Carvalho Chehab, Stephen Boyd, Seung-Woo Kim, Hans Verkuil,
	Kyungmin Park

[-- Attachment #1: Type: text/plain, Size: 2522 bytes --]

Hi Maciej,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v4.16-rc2 next-20180219]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Maciej-Purski/Use-clk-bulk-API-in-exynos5433-drivers/20180220-054431
base:   git://linuxtv.org/media_tree.git master
config: sparc64-allmodconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sparc64 

All warnings (new ones prefixed by >>):

   drivers/media/platform/s5p-mfc/s5p_mfc_pm.c: In function 's5p_mfc_init_pm':
>> drivers/media/platform/s5p-mfc/s5p_mfc_pm.c:39:7: warning: passing argument 3 of 'devm_clk_bulk_alloc' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
          pm->clk_names);
          ^~
   In file included from drivers/media/platform/s5p-mfc/s5p_mfc_pm.c:13:0:
   include/linux/clk.h:654:37: note: expected 'const char **' but argument is of type 'const char * const*'
    static inline struct clk_bulk_data *devm_clk_bulk_alloc(struct device *dev,
                                        ^~~~~~~~~~~~~~~~~~~

vim +39 drivers/media/platform/s5p-mfc/s5p_mfc_pm.c

    24	
    25	int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
    26	{
    27		int ret;
    28	
    29		pm = &dev->pm;
    30		p_dev = dev;
    31	
    32		pm->num_clocks = dev->variant->num_clocks;
    33		pm->clk_names = dev->variant->clk_names;
    34		pm->device = &dev->plat_dev->dev;
    35		pm->clock_gate = NULL;
    36	
    37		/* clock control */
    38		pm->clocks = devm_clk_bulk_alloc(pm->device, pm->num_clocks,
  > 39						 pm->clk_names);
    40		if (IS_ERR(pm->clocks))
    41			return PTR_ERR(pm->clocks);
    42	
    43		ret = devm_clk_bulk_get(pm->device, pm->num_clocks, pm->clocks);
    44		if (ret < 0)
    45			return ret;
    46	
    47		if (dev->variant->use_clock_gating)
    48			pm->clock_gate = pm->clocks[0].clk;
    49	
    50		pm_runtime_enable(pm->device);
    51		atomic_set(&clk_ref, 0);
    52		return 0;
    53	}
    54	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 53401 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/8] clk: Add clk_bulk_alloc functions
  2018-02-19 16:29       ` Robin Murphy
@ 2018-02-20  9:36         ` Marek Szyprowski
  2018-02-20 14:19           ` Robin Murphy
  2018-03-15 22:55           ` Stephen Boyd
  0 siblings, 2 replies; 18+ messages in thread
From: Marek Szyprowski @ 2018-02-20  9:36 UTC (permalink / raw)
  To: Robin Murphy, Maciej Purski, linux-media, linux-samsung-soc,
	linux-arm-kernel, dri-devel, linux-kernel, linux-clk
  Cc: David Airlie, Michael Turquette, Kamil Debski, Andrzej Hajda,
	Sylwester Nawrocki, Thibault Saunier, Joonyoung Shim,
	Russell King, Krzysztof Kozlowski, Javier Martinez Canillas,
	Kukjin Kim, Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Inki Dae,
	Jeongtae Park, Jacek Anaszewski, Andrzej Pietrasiewicz,
	Mauro Carvalho Chehab, Stephen Boyd, Seung-Woo Kim, Hans Verkuil,
	Kyungmin Park

Hi Robin,

On 2018-02-19 17:29, Robin Murphy wrote:
> Hi Maciej,
>
> On 19/02/18 15:43, Maciej Purski wrote:
>> When a driver is going to use clk_bulk_get() function, it has to
>> initialize an array of clk_bulk_data, by filling its id fields.
>>
>> Add a new function to the core, which dynamically allocates
>> clk_bulk_data array and fills its id fields. Add clk_bulk_free()
>> function, which frees the array allocated by clk_bulk_alloc() function.
>> Add a managed version of clk_bulk_alloc().
>
> Seeing how every subsequent patch ends up with the roughly this same 
> stanza:
>
>     x = devm_clk_bulk_alloc(dev, num, names);
>     if (IS_ERR(x)
>         return PTR_ERR(x);
>     ret = devm_clk_bulk_get(dev, x, num);
>
> I wonder if it might be better to simply implement:
>
>     int devm_clk_bulk_alloc_get(dev, &x, num, names)
>
> that does the whole lot in one go, and let drivers that want to do 
> more fiddly things continue to open-code the allocation.
>
> But perhaps that's an abstraction too far... I'm not all that familiar 
> with the lie of the land here.

Hmmm. This patchset clearly shows, that it would be much simpler if we
get rid of clk_bulk_data structure at all and let clk_bulk_* functions
to operate on struct clk *array[]. Typically the list of clock names
is already in some kind of array (taken from driver data or statically
embedded into driver), so there is little benefit from duplicating it
in clk_bulk_data. Sadly, I missed clk_bulk_* api discussion and maybe
there are other benefits from this approach.

If not, I suggest simplifying clk_bulk_* api by dropping clk_bulk_data
structure and switching to clock ptr array:

int clk_bulk_get(struct device *dev, int num_clock, struct clk *clocks[],
                  const char *clk_names[]);
int clk_bulk_prepare(int num_clks, struct clk *clks[]);
int clk_bulk_enable(int num_clks, struct clk *clks[]);
...



>
>> Signed-off-by: Maciej Purski <m.purski@samsung.com>
>> ---
>>   drivers/clk/clk-bulk.c   | 16 ++++++++++++
>>   drivers/clk/clk-devres.c | 37 +++++++++++++++++++++++++---
>>   include/linux/clk.h      | 64 
>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 113 insertions(+), 4 deletions(-)
>>
>
> [...]
>> @@ -598,6 +645,23 @@ struct clk *clk_get_sys(const char *dev_id, 
>> const char *con_id);
>>     #else /* !CONFIG_HAVE_CLK */
>>   +static inline struct clk_bulk_data *clk_bulk_alloc(int num_clks,
>> +                           const char **clk_ids)
>> +{
>> +    return NULL;
>
> Either way, is it intentional not returning an ERR_PTR() value in this 
> case? Since NULL will pass an IS_ERR() check, it seems a bit fragile 
> for an allocation call to apparently succeed when the whole API is 
> configured out (and I believe introducing new uses of IS_ERR_OR_NULL() 
> is in general strongly discouraged.)
>
> Robin.
>
>> +}
>> +
>> +static inline struct clk_bulk_data *devm_clk_bulk_alloc(struct 
>> device *dev,
>> +                            int num_clks,
>> +                            const char **clk_ids)
>> +{
>> +    return NULL;
>> +}
>> +
>> +static inline void clk_bulk_free(struct clk_bulk_data *clks)
>> +{
>> +}
>> +
>>   static inline struct clk *clk_get(struct device *dev, const char *id)
>>   {
>>       return NULL;
>
Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/8] clk: Add clk_bulk_alloc functions
  2018-02-20  9:36         ` Marek Szyprowski
@ 2018-02-20 14:19           ` Robin Murphy
  2018-03-15 22:55           ` Stephen Boyd
  1 sibling, 0 replies; 18+ messages in thread
From: Robin Murphy @ 2018-02-20 14:19 UTC (permalink / raw)
  To: Marek Szyprowski, Maciej Purski, linux-media, linux-samsung-soc,
	linux-arm-kernel, dri-devel, linux-kernel, linux-clk
  Cc: David Airlie, Michael Turquette, Kamil Debski, Andrzej Hajda,
	Sylwester Nawrocki, Thibault Saunier, Joonyoung Shim,
	Russell King, Krzysztof Kozlowski, Javier Martinez Canillas,
	Kukjin Kim, Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Inki Dae,
	Jeongtae Park, Jacek Anaszewski, Andrzej Pietrasiewicz,
	Mauro Carvalho Chehab, Stephen Boyd, Seung-Woo Kim, Hans Verkuil,
	Kyungmin Park

Hi Marek,

On 20/02/18 09:36, Marek Szyprowski wrote:
> Hi Robin,
> 
> On 2018-02-19 17:29, Robin Murphy wrote:
>> Hi Maciej,
>>
>> On 19/02/18 15:43, Maciej Purski wrote:
>>> When a driver is going to use clk_bulk_get() function, it has to
>>> initialize an array of clk_bulk_data, by filling its id fields.
>>>
>>> Add a new function to the core, which dynamically allocates
>>> clk_bulk_data array and fills its id fields. Add clk_bulk_free()
>>> function, which frees the array allocated by clk_bulk_alloc() function.
>>> Add a managed version of clk_bulk_alloc().
>>
>> Seeing how every subsequent patch ends up with the roughly this same 
>> stanza:
>>
>>     x = devm_clk_bulk_alloc(dev, num, names);
>>     if (IS_ERR(x)
>>         return PTR_ERR(x);
>>     ret = devm_clk_bulk_get(dev, x, num);
>>
>> I wonder if it might be better to simply implement:
>>
>>     int devm_clk_bulk_alloc_get(dev, &x, num, names)
>>
>> that does the whole lot in one go, and let drivers that want to do 
>> more fiddly things continue to open-code the allocation.
>>
>> But perhaps that's an abstraction too far... I'm not all that familiar 
>> with the lie of the land here.
> 
> Hmmm. This patchset clearly shows, that it would be much simpler if we
> get rid of clk_bulk_data structure at all and let clk_bulk_* functions
> to operate on struct clk *array[]. Typically the list of clock names
> is already in some kind of array (taken from driver data or statically
> embedded into driver), so there is little benefit from duplicating it
> in clk_bulk_data. Sadly, I missed clk_bulk_* api discussion and maybe
> there are other benefits from this approach.
> 
> If not, I suggest simplifying clk_bulk_* api by dropping clk_bulk_data
> structure and switching to clock ptr array:
> 
> int clk_bulk_get(struct device *dev, int num_clock, struct clk *clocks[],
>                   const char *clk_names[]);
> int clk_bulk_prepare(int num_clks, struct clk *clks[]);
> int clk_bulk_enable(int num_clks, struct clk *clks[]);
> ...

Yes, that's certainly a possibility; if on the other hand there are 
desirable reasons for the encapsulation (personally, I do think it's 
quite neat), then maybe num_clocks should get pushed down into 
clk_bulk_data as well - then with dedicated alloc/free functions as 
proposed here it could become a simple opaque cookie as far as callers 
are concerned.

I also haven't looked into the origins of the bulk API design, though; 
I've just been familiarising myself from the perspective of reviewing 
general clk API usage in drivers.

Robin.

>>> Signed-off-by: Maciej Purski <m.purski@samsung.com>
>>> ---
>>>   drivers/clk/clk-bulk.c   | 16 ++++++++++++
>>>   drivers/clk/clk-devres.c | 37 +++++++++++++++++++++++++---
>>>   include/linux/clk.h      | 64 
>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>>   3 files changed, 113 insertions(+), 4 deletions(-)
>>>
>>
>> [...]
>>> @@ -598,6 +645,23 @@ struct clk *clk_get_sys(const char *dev_id, 
>>> const char *con_id);
>>>     #else /* !CONFIG_HAVE_CLK */
>>>   +static inline struct clk_bulk_data *clk_bulk_alloc(int num_clks,
>>> +                           const char **clk_ids)
>>> +{
>>> +    return NULL;
>>
>> Either way, is it intentional not returning an ERR_PTR() value in this 
>> case? Since NULL will pass an IS_ERR() check, it seems a bit fragile 
>> for an allocation call to apparently succeed when the whole API is 
>> configured out (and I believe introducing new uses of IS_ERR_OR_NULL() 
>> is in general strongly discouraged.)
>>
>> Robin.
>>
>>> +}
>>> +
>>> +static inline struct clk_bulk_data *devm_clk_bulk_alloc(struct 
>>> device *dev,
>>> +                            int num_clks,
>>> +                            const char **clk_ids)
>>> +{
>>> +    return NULL;
>>> +}
>>> +
>>> +static inline void clk_bulk_free(struct clk_bulk_data *clks)
>>> +{
>>> +}
>>> +
>>>   static inline struct clk *clk_get(struct device *dev, const char *id)
>>>   {
>>>       return NULL;
>>
> Best regards

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/8] clk: Add clk_bulk_alloc functions
  2018-02-20  9:36         ` Marek Szyprowski
  2018-02-20 14:19           ` Robin Murphy
@ 2018-03-15 22:55           ` Stephen Boyd
  1 sibling, 0 replies; 18+ messages in thread
From: Stephen Boyd @ 2018-03-15 22:55 UTC (permalink / raw)
  To: Maciej Purski, Marek Szyprowski, Robin Murphy, dri-devel,
	linux-arm-kernel, linux-clk, linux-kernel, linux-media,
	linux-samsung-soc
  Cc: David Airlie, Michael Turquette, Kamil Debski, Andrzej Hajda,
	Sylwester Nawrocki, Thibault Saunier, Joonyoung Shim,
	Russell King, Krzysztof Kozlowski, Javier Martinez Canillas,
	Kukjin Kim, Hoegeun Kwon, Bartlomiej Zolnierkiewicz, Inki Dae,
	Jeongtae Park, Jacek Anaszewski, Andrzej Pietrasiewicz,
	Mauro Carvalho Chehab, Seung-Woo Kim, Hans Verkuil,
	Kyungmin Park

Quoting Marek Szyprowski (2018-02-20 01:36:03)
> Hi Robin,
> 
> On 2018-02-19 17:29, Robin Murphy wrote:
> >
> > Seeing how every subsequent patch ends up with the roughly this same 
> > stanza:
> >
> >     x = devm_clk_bulk_alloc(dev, num, names);
> >     if (IS_ERR(x)
> >         return PTR_ERR(x);
> >     ret = devm_clk_bulk_get(dev, x, num);
> >
> > I wonder if it might be better to simply implement:
> >
> >     int devm_clk_bulk_alloc_get(dev, &x, num, names)
> >
> > that does the whole lot in one go, and let drivers that want to do 
> > more fiddly things continue to open-code the allocation.
> >
> > But perhaps that's an abstraction too far... I'm not all that familiar 
> > with the lie of the land here.
> 
> Hmmm. This patchset clearly shows, that it would be much simpler if we
> get rid of clk_bulk_data structure at all and let clk_bulk_* functions
> to operate on struct clk *array[]. Typically the list of clock names
> is already in some kind of array (taken from driver data or statically
> embedded into driver), so there is little benefit from duplicating it
> in clk_bulk_data. Sadly, I missed clk_bulk_* api discussion and maybe
> there are other benefits from this approach.
> 
> If not, I suggest simplifying clk_bulk_* api by dropping clk_bulk_data
> structure and switching to clock ptr array:
> 
> int clk_bulk_get(struct device *dev, int num_clock, struct clk *clocks[],
>                   const char *clk_names[]);
> int clk_bulk_prepare(int num_clks, struct clk *clks[]);
> int clk_bulk_enable(int num_clks, struct clk *clks[]);
> ...
> 

If you have an array of pointers to names of clks then we can put the
struct clk pointers adjacent to them at the same time. I suppose the
problem there is that some drivers want to mark that array of pointers
to names as const. And then we can't update the clk pointers next to
them.

This is the same design that regulators has done so that's why it's
written like this for clks. Honestly, we're talking about a handful of
pointers here so I'm not sure it really matters much. Just duplicate the
pointer and be done if you want to mark the array of names as const or
have your const 'setup' structure point to the bulk_data array that you
define statically non-const somewhere globally.

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2018-03-15 22:55 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20180219154456eucas1p178a82b3bb643028dc7c99ccca9c6eaca@eucas1p1.samsung.com>
2018-02-19 15:43 ` [PATCH 0/8] Use clk bulk API in exynos5433 drivers Maciej Purski
     [not found]   ` <CGME20180219154456eucas1p15f4073beaf61312238f142f217a8bb3c@eucas1p1.samsung.com>
2018-02-19 15:43     ` [PATCH 1/8] clk: Add clk_bulk_alloc functions Maciej Purski
2018-02-19 16:29       ` Robin Murphy
2018-02-20  9:36         ` Marek Szyprowski
2018-02-20 14:19           ` Robin Murphy
2018-03-15 22:55           ` Stephen Boyd
2018-02-19 18:22       ` Emil Velikov
     [not found]   ` <CGME20180219154457eucas1p163264992903698a8878aa5abbc8aa17b@eucas1p1.samsung.com>
2018-02-19 15:44     ` [PATCH 2/8] media: s5p-jpeg: Use bulk clk API Maciej Purski
2018-02-20  0:22       ` kbuild test robot
     [not found]   ` <CGME20180219154458eucas1p1b4e728757e78f3d5dde5c9aa565a5d20@eucas1p1.samsung.com>
2018-02-19 15:44     ` [PATCH 3/8] drm/exynos/decon: Use clk bulk API Maciej Purski
     [not found]   ` <CGME20180219154459eucas1p147525b88de5d34f646aa25cb8de1f1d0@eucas1p1.samsung.com>
2018-02-19 15:44     ` [PATCH 4/8] drm/exynos/dsi: " Maciej Purski
2018-02-20  1:39       ` kbuild test robot
     [not found]   ` <CGME20180219154500eucas1p25e9f3bf44901cb2bbe9720cdc5bdd855@eucas1p2.samsung.com>
2018-02-19 15:44     ` [PATCH 5/8] drm/exynos: mic: " Maciej Purski
     [not found]   ` <CGME20180219154501eucas1p1e16a883d2eb0c8a99bafce5d71656066@eucas1p1.samsung.com>
2018-02-19 15:44     ` [PATCH 6/8] drm/exynos/hdmi: " Maciej Purski
     [not found]   ` <CGME20180219154502eucas1p20e8daf3edc6737817f8d62db5a2099f2@eucas1p2.samsung.com>
2018-02-19 15:44     ` [PATCH 7/8] [media] exynos-gsc: " Maciej Purski
2018-02-19 22:38       ` kbuild test robot
     [not found]   ` <CGME20180219154503eucas1p1c8893411994bd1152d0ce5b386118416@eucas1p1.samsung.com>
2018-02-19 15:44     ` [PATCH 8/8] [media] s5p-mfc: " Maciej Purski
2018-02-20  1:56       ` kbuild test robot

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).