All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/22] OMAP DRM fixes and improvements
@ 2016-12-14  0:27 Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 01/22] drm: omapdrm: fb: Limit number of planes per framebuffer to two Laurent Pinchart
                   ` (22 more replies)
  0 siblings, 23 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Hello,

Here's the fourth version of my current stack of pending patches for the
omapdrm driver.

All comments received for v3 have been considered and patches updated where
applicable. Patches 21/22 and 22/22 have been added, individual changelogs are
available in all the patches when they have been modified.

The most notable change in this series is still the rework of the IRQ handling
code (patches 06/22 to 19/22) that, beside simplifying the code, ensures that
the vblank count and timestamp get updated properly in order to be reported to
userspace.

The series is based on top of Dave's drm-next branch.

Laurent Pinchart (22):
  drm: omapdrm: fb: Limit number of planes per framebuffer to two
  drm: omapdrm: fb: Use format information provided by the DRM core
  drm: omapdrm: fb: Simplify objects lookup when creating framebuffer
  drm: omapdrm: fb: Simplify mode command checks when creating
    framebuffer
  drm: omapdrm: fb: Turn framebuffer creation error messages into debug
  drm: omapdrm: Handle FIFO underflow IRQs internally
  drm: omapdrm: Handle CRTC error IRQs directly
  drm: omapdrm: Handle OCP error IRQ directly
  drm: omapdrm: Replace DSS manager state check with omapdrm CRTC state
  drm: omapdrm: Let the DRM core skip plane commit on inactive CRTCs
  drm: omapdrm: Check the CRTC software state at enable/disable time
  drm: omapdrm: Prevent processing the same event multiple times
  drm: omapdrm: Use a spinlock to protect the CRTC pending flag
  drm: omapdrm: Keep vblank interrupt enabled while CRTC is active
  drm: omapdrm: Don't expose the omap_irq_(un)register() functions
  drm: omapdrm: Remove unused parameter from omap_drm_irq handler
  drm: omapdrm: Don't call DISPC power handling in IRQ wait functions
  drm: omapdrm: Inline the pipe2vbl function
  drm: omapdrm: Simplify IRQ wait implementation
  drm: omapdrm: Remove global variables
  drm: omapdrm: Use sizeof(*var) instead of sizeof(type) for structures
  drm: omapdrm: Perform initialization/cleanup at probe/remove time

 drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c |   2 +-
 drivers/gpu/drm/omapdrm/dss/dispc.c             |  27 ++-
 drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c |   3 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h           |   1 -
 drivers/gpu/drm/omapdrm/omap_connector.c        |   6 +-
 drivers/gpu/drm/omapdrm/omap_crtc.c             | 127 +++++++------
 drivers/gpu/drm/omapdrm/omap_dmm_tiler.c        |   4 +-
 drivers/gpu/drm/omapdrm/omap_drv.c              | 219 ++++++++++-----------
 drivers/gpu/drm/omapdrm/omap_drv.h              |  51 +----
 drivers/gpu/drm/omapdrm/omap_encoder.c          |   2 +-
 drivers/gpu/drm/omapdrm/omap_fb.c               | 164 ++++++++--------
 drivers/gpu/drm/omapdrm/omap_irq.c              | 242 +++++++++++++-----------
 drivers/gpu/drm/omapdrm/omap_plane.c            |  24 ---
 13 files changed, 418 insertions(+), 454 deletions(-)

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 01/22] drm: omapdrm: fb: Limit number of planes per framebuffer to two
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 02/22] drm: omapdrm: fb: Use format information provided by the DRM core Laurent Pinchart
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The only multi-planar format supported by the driver is NV12, there will
thus never be more than two planes per framebuffer.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/omap_fb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 5f3337f1e9aa..7646df33f9a1 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -36,7 +36,7 @@ struct format {
 	struct {
 		int stride_bpp;           /* this times width is stride */
 		int sub_y;                /* sub-sample in y dimension */
-	} planes[4];
+	} planes[2];
 	bool yuv;
 };
 
@@ -90,7 +90,7 @@ struct omap_framebuffer {
 	struct drm_framebuffer base;
 	int pin_count;
 	const struct format *format;
-	struct plane planes[4];
+	struct plane planes[2];
 	/* lock for pinning (pin_count and planes.paddr) */
 	struct mutex lock;
 };
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 02/22] drm: omapdrm: fb: Use format information provided by the DRM core
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 01/22] drm: omapdrm: fb: Limit number of planes per framebuffer to two Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14 10:07   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 03/22] drm: omapdrm: fb: Simplify objects lookup when creating framebuffer Laurent Pinchart
                   ` (20 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The driver stores in a custom structure named format several pieces of
information about the format that are available in the DRM core. Remove
them and get the information from the DRM core instead.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v3:

- Fix subsampling computation by checking the plane number correctly
---
 drivers/gpu/drm/omapdrm/omap_fb.c | 91 ++++++++++++++++++++-------------------
 1 file changed, 46 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 7646df33f9a1..6315d68989fc 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -29,37 +29,30 @@
  * framebuffer funcs
  */
 
-/* per-format info: */
-struct format {
+/* DSS to DRM formats mapping */
+static const struct {
 	enum omap_color_mode dss_format;
 	uint32_t pixel_format;
-	struct {
-		int stride_bpp;           /* this times width is stride */
-		int sub_y;                /* sub-sample in y dimension */
-	} planes[2];
-	bool yuv;
-};
-
-static const struct format formats[] = {
+} formats[] = {
 	/* 16bpp [A]RGB: */
-	{ OMAP_DSS_COLOR_RGB16,       DRM_FORMAT_RGB565,   {{2, 1}}, false }, /* RGB16-565 */
-	{ OMAP_DSS_COLOR_RGB12U,      DRM_FORMAT_RGBX4444, {{2, 1}}, false }, /* RGB12x-4444 */
-	{ OMAP_DSS_COLOR_RGBX16,      DRM_FORMAT_XRGB4444, {{2, 1}}, false }, /* xRGB12-4444 */
-	{ OMAP_DSS_COLOR_RGBA16,      DRM_FORMAT_RGBA4444, {{2, 1}}, false }, /* RGBA12-4444 */
-	{ OMAP_DSS_COLOR_ARGB16,      DRM_FORMAT_ARGB4444, {{2, 1}}, false }, /* ARGB16-4444 */
-	{ OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555, {{2, 1}}, false }, /* xRGB15-1555 */
-	{ OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555, {{2, 1}}, false }, /* ARGB16-1555 */
+	{ OMAP_DSS_COLOR_RGB16,       DRM_FORMAT_RGB565 },   /* RGB16-565 */
+	{ OMAP_DSS_COLOR_RGB12U,      DRM_FORMAT_RGBX4444 }, /* RGB12x-4444 */
+	{ OMAP_DSS_COLOR_RGBX16,      DRM_FORMAT_XRGB4444 }, /* xRGB12-4444 */
+	{ OMAP_DSS_COLOR_RGBA16,      DRM_FORMAT_RGBA4444 }, /* RGBA12-4444 */
+	{ OMAP_DSS_COLOR_ARGB16,      DRM_FORMAT_ARGB4444 }, /* ARGB16-4444 */
+	{ OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555 }, /* xRGB15-1555 */
+	{ OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555 }, /* ARGB16-1555 */
 	/* 24bpp RGB: */
-	{ OMAP_DSS_COLOR_RGB24P,      DRM_FORMAT_RGB888,   {{3, 1}}, false }, /* RGB24-888 */
+	{ OMAP_DSS_COLOR_RGB24P,      DRM_FORMAT_RGB888 },   /* RGB24-888 */
 	/* 32bpp [A]RGB: */
-	{ OMAP_DSS_COLOR_RGBX32,      DRM_FORMAT_RGBX8888, {{4, 1}}, false }, /* RGBx24-8888 */
-	{ OMAP_DSS_COLOR_RGB24U,      DRM_FORMAT_XRGB8888, {{4, 1}}, false }, /* xRGB24-8888 */
-	{ OMAP_DSS_COLOR_RGBA32,      DRM_FORMAT_RGBA8888, {{4, 1}}, false }, /* RGBA32-8888 */
-	{ OMAP_DSS_COLOR_ARGB32,      DRM_FORMAT_ARGB8888, {{4, 1}}, false }, /* ARGB32-8888 */
+	{ OMAP_DSS_COLOR_RGBX32,      DRM_FORMAT_RGBX8888 }, /* RGBx24-8888 */
+	{ OMAP_DSS_COLOR_RGB24U,      DRM_FORMAT_XRGB8888 }, /* xRGB24-8888 */
+	{ OMAP_DSS_COLOR_RGBA32,      DRM_FORMAT_RGBA8888 }, /* RGBA32-8888 */
+	{ OMAP_DSS_COLOR_ARGB32,      DRM_FORMAT_ARGB8888 }, /* ARGB32-8888 */
 	/* YUV: */
-	{ OMAP_DSS_COLOR_NV12,        DRM_FORMAT_NV12,     {{1, 1}, {1, 2}}, true },
-	{ OMAP_DSS_COLOR_YUV2,        DRM_FORMAT_YUYV,     {{2, 1}}, true },
-	{ OMAP_DSS_COLOR_UYVY,        DRM_FORMAT_UYVY,     {{2, 1}}, true },
+	{ OMAP_DSS_COLOR_NV12,        DRM_FORMAT_NV12 },
+	{ OMAP_DSS_COLOR_YUV2,        DRM_FORMAT_YUYV },
+	{ OMAP_DSS_COLOR_UYVY,        DRM_FORMAT_UYVY },
 };
 
 /* convert from overlay's pixel formats bitmask to an array of fourcc's */
@@ -89,7 +82,8 @@ struct plane {
 struct omap_framebuffer {
 	struct drm_framebuffer base;
 	int pin_count;
-	const struct format *format;
+	const struct drm_format_info *format;
+	enum omap_color_mode dss_format;
 	struct plane planes[2];
 	/* lock for pinning (pin_count and planes.paddr) */
 	struct mutex lock;
@@ -128,13 +122,13 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
 };
 
 static uint32_t get_linear_addr(struct plane *plane,
-		const struct format *format, int n, int x, int y)
+		const struct drm_format_info *format, int n, int x, int y)
 {
 	uint32_t offset;
 
-	offset = plane->offset +
-			(x * format->planes[n].stride_bpp) +
-			(y * plane->pitch / format->planes[n].sub_y);
+	offset = plane->offset
+	       + (x * format->cpp[n] / (n == 0 ? 1 : format->hsub))
+	       + (y * plane->pitch / (n == 0 ? 1 : format->vsub));
 
 	return plane->paddr + offset;
 }
@@ -153,11 +147,11 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
 		struct omap_drm_window *win, struct omap_overlay_info *info)
 {
 	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-	const struct format *format = omap_fb->format;
+	const struct drm_format_info *format = omap_fb->format;
 	struct plane *plane = &omap_fb->planes[0];
 	uint32_t x, y, orient = 0;
 
-	info->color_mode = format->dss_format;
+	info->color_mode = omap_fb->dss_format;
 
 	info->pos_x      = win->crtc_x;
 	info->pos_y      = win->crtc_y;
@@ -231,9 +225,9 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
 	}
 
 	/* convert to pixels: */
-	info->screen_width /= format->planes[0].stride_bpp;
+	info->screen_width /= format->cpp[0];
 
-	if (format->dss_format == OMAP_DSS_COLOR_NV12) {
+	if (omap_fb->dss_format == OMAP_DSS_COLOR_NV12) {
 		plane = &omap_fb->planes[1];
 
 		if (info->rotation_type == OMAP_DSS_ROT_TILER) {
@@ -382,23 +376,26 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
 struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 		const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
 {
+	const struct drm_format_info *format = NULL;
 	struct omap_framebuffer *omap_fb = NULL;
 	struct drm_framebuffer *fb = NULL;
-	const struct format *format = NULL;
-	int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format);
+	enum omap_color_mode dss_format = 0;
+	int ret, i;
 
 	DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",
 			dev, mode_cmd, mode_cmd->width, mode_cmd->height,
 			(char *)&mode_cmd->pixel_format);
 
+	format = drm_format_info(mode_cmd->pixel_format);
+
 	for (i = 0; i < ARRAY_SIZE(formats); i++) {
 		if (formats[i].pixel_format == mode_cmd->pixel_format) {
-			format = &formats[i];
+			dss_format = formats[i].dss_format;
 			break;
 		}
 	}
 
-	if (!format) {
+	if (!format || !dss_format) {
 		dev_err(dev->dev, "unsupported pixel format: %4.4s\n",
 				(char *)&mode_cmd->pixel_format);
 		ret = -EINVAL;
@@ -413,28 +410,32 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 
 	fb = &omap_fb->base;
 	omap_fb->format = format;
+	omap_fb->dss_format = dss_format;
 	mutex_init(&omap_fb->lock);
 
-	for (i = 0; i < n; i++) {
+	for (i = 0; i < format->num_planes; i++) {
 		struct plane *plane = &omap_fb->planes[i];
-		int size, pitch = mode_cmd->pitches[i];
+		unsigned int pitch = mode_cmd->pitches[i];
+		unsigned int hsub = i == 0 ? 1 : format->hsub;
+		unsigned int vsub = i == 0 ? 1 : format->vsub;
+		unsigned int size;
 
-		if (pitch < (mode_cmd->width * format->planes[i].stride_bpp)) {
+		if (pitch < mode_cmd->width * format->cpp[i] / hsub) {
 			dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n",
-					pitch, mode_cmd->width * format->planes[i].stride_bpp);
+				pitch, mode_cmd->width * format->cpp[i] / hsub);
 			ret = -EINVAL;
 			goto fail;
 		}
 
-		if (pitch % format->planes[i].stride_bpp != 0) {
+		if (pitch % format->cpp[i] != 0) {
 			dev_err(dev->dev,
 				"buffer pitch (%d bytes) is not a multiple of pixel size (%d bytes)\n",
-				pitch, format->planes[i].stride_bpp);
+				pitch, format->cpp[i]);
 			ret = -EINVAL;
 			goto fail;
 		}
 
-		size = pitch * mode_cmd->height / format->planes[i].sub_y;
+		size = pitch * mode_cmd->height / vsub;
 
 		if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) {
 			dev_err(dev->dev, "provided buffer object is too small! %d < %d\n",
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 03/22] drm: omapdrm: fb: Simplify objects lookup when creating framebuffer
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 01/22] drm: omapdrm: fb: Limit number of planes per framebuffer to two Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 02/22] drm: omapdrm: fb: Use format information provided by the DRM core Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 04/22] drm: omapdrm: fb: Simplify mode command checks " Laurent Pinchart
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Merge the single-user objects_lookup inline function into its caller,
allowing reuse of the error code path.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/omap_drv.h | 25 -------------------------
 drivers/gpu/drm/omapdrm/omap_fb.c  | 29 ++++++++++++++++++-----------
 2 files changed, 18 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 7d9dd5400cef..919c14d3503c 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -236,29 +236,4 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
 uint32_t pipe2vbl(struct drm_crtc *crtc);
 struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder);
 
-/* should these be made into common util helpers?
- */
-
-static inline int objects_lookup(
-		struct drm_file *filp, uint32_t pixel_format,
-		struct drm_gem_object **bos, const uint32_t *handles)
-{
-	int i, n = drm_format_num_planes(pixel_format);
-
-	for (i = 0; i < n; i++) {
-		bos[i] = drm_gem_object_lookup(filp, handles[i]);
-		if (!bos[i])
-			goto fail;
-
-	}
-
-	return 0;
-
-fail:
-	while (--i > 0)
-		drm_gem_object_unreference_unlocked(bos[i]);
-
-	return -ENOENT;
-}
-
 #endif /* __OMAP_DRV_H__ */
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 6315d68989fc..195ab4c86244 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -354,22 +354,29 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
 		struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)
 {
+	unsigned int num_planes = drm_format_num_planes(mode_cmd->pixel_format);
 	struct drm_gem_object *bos[4];
 	struct drm_framebuffer *fb;
-	int ret;
+	int i;
 
-	ret = objects_lookup(file, mode_cmd->pixel_format,
-			bos, mode_cmd->handles);
-	if (ret)
-		return ERR_PTR(ret);
+	for (i = 0; i < num_planes; i++) {
+		bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
+		if (!bos[i]) {
+			fb = ERR_PTR(-ENOENT);
+			goto error;
+		}
+	}
 
 	fb = omap_framebuffer_init(dev, mode_cmd, bos);
-	if (IS_ERR(fb)) {
-		int i, n = drm_format_num_planes(mode_cmd->pixel_format);
-		for (i = 0; i < n; i++)
-			drm_gem_object_unreference_unlocked(bos[i]);
-		return fb;
-	}
+	if (IS_ERR(fb))
+		goto error;
+
+	return fb;
+
+error:
+	while (--i > 0)
+		drm_gem_object_unreference_unlocked(bos[i]);
+
 	return fb;
 }
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 04/22] drm: omapdrm: fb: Simplify mode command checks when creating framebuffer
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (2 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 03/22] drm: omapdrm: fb: Simplify objects lookup when creating framebuffer Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 05/22] drm: omapdrm: fb: Turn framebuffer creation error messages into debug Laurent Pinchart
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The hardware requires all planes to have an identical pitch in number of
pixels. Given that all supported formats use the same number of bytes
per pixel in all planes, framebuffer creation checks can be simplified.
The implementations assumes that no format use more than two planes
which is true with the existing hardware.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
Changes since v3:

- Remove pitch check already performed by the DRM core

Changes since v1:

- Clarify commit message and mention explicitly in the code that only
  one and two planes formats are supported.
- Rebase on top of the switch to drm_format_info()
---
 drivers/gpu/drm/omapdrm/omap_fb.c | 50 ++++++++++++++++++---------------------
 1 file changed, 23 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 195ab4c86244..016aac9a7731 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -387,6 +387,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 	struct omap_framebuffer *omap_fb = NULL;
 	struct drm_framebuffer *fb = NULL;
 	enum omap_color_mode dss_format = 0;
+	unsigned int pitch = mode_cmd->pitches[0];
 	int ret, i;
 
 	DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",
@@ -420,41 +421,36 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 	omap_fb->dss_format = dss_format;
 	mutex_init(&omap_fb->lock);
 
+	/*
+	 * The code below assumes that no format use more than two planes, and
+	 * that the two planes of multiplane formats need the same number of
+	 * bytes per pixel.
+	 */
+	if (format->num_planes == 2 && pitch != mode_cmd->pitches[1]) {
+		dev_err(dev->dev, "pitches differ between planes 0 and 1\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (pitch % format->cpp[0]) {
+		dev_err(dev->dev,
+			"buffer pitch (%u bytes) is not a multiple of pixel size (%u bytes)\n",
+			pitch, format->cpp[0]);
+		ret = -EINVAL;
+		goto fail;
+	}
+
 	for (i = 0; i < format->num_planes; i++) {
 		struct plane *plane = &omap_fb->planes[i];
-		unsigned int pitch = mode_cmd->pitches[i];
-		unsigned int hsub = i == 0 ? 1 : format->hsub;
 		unsigned int vsub = i == 0 ? 1 : format->vsub;
 		unsigned int size;
 
-		if (pitch < mode_cmd->width * format->cpp[i] / hsub) {
-			dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n",
-				pitch, mode_cmd->width * format->cpp[i] / hsub);
-			ret = -EINVAL;
-			goto fail;
-		}
-
-		if (pitch % format->cpp[i] != 0) {
-			dev_err(dev->dev,
-				"buffer pitch (%d bytes) is not a multiple of pixel size (%d bytes)\n",
-				pitch, format->cpp[i]);
-			ret = -EINVAL;
-			goto fail;
-		}
-
 		size = pitch * mode_cmd->height / vsub;
 
-		if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) {
-			dev_err(dev->dev, "provided buffer object is too small! %d < %d\n",
-					bos[i]->size - mode_cmd->offsets[i], size);
-			ret = -EINVAL;
-			goto fail;
-		}
-
-		if (i > 0 && pitch != mode_cmd->pitches[i - 1]) {
+		if (size > omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i]) {
 			dev_err(dev->dev,
-				"pitches are not the same between framebuffer planes %d != %d\n",
-				pitch, mode_cmd->pitches[i - 1]);
+				"provided buffer object is too small! %d < %d\n",
+				bos[i]->size - mode_cmd->offsets[i], size);
 			ret = -EINVAL;
 			goto fail;
 		}
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 05/22] drm: omapdrm: fb: Turn framebuffer creation error messages into debug
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (3 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 04/22] drm: omapdrm: fb: Simplify mode command checks " Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 06/22] drm: omapdrm: Handle FIFO underflow IRQs internally Laurent Pinchart
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Don't print userspace parameters validation failures as error messages
to avoid giving userspace the ability to flood the kernel log.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/omap_fb.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 016aac9a7731..a30f2060c1d6 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -404,8 +404,8 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 	}
 
 	if (!format || !dss_format) {
-		dev_err(dev->dev, "unsupported pixel format: %4.4s\n",
-				(char *)&mode_cmd->pixel_format);
+		dev_dbg(dev->dev, "unsupported pixel format: %4.4s\n",
+			(char *)&mode_cmd->pixel_format);
 		ret = -EINVAL;
 		goto fail;
 	}
@@ -427,13 +427,13 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 	 * bytes per pixel.
 	 */
 	if (format->num_planes == 2 && pitch != mode_cmd->pitches[1]) {
-		dev_err(dev->dev, "pitches differ between planes 0 and 1\n");
+		dev_dbg(dev->dev, "pitches differ between planes 0 and 1\n");
 		ret = -EINVAL;
 		goto fail;
 	}
 
 	if (pitch % format->cpp[0]) {
-		dev_err(dev->dev,
+		dev_dbg(dev->dev,
 			"buffer pitch (%u bytes) is not a multiple of pixel size (%u bytes)\n",
 			pitch, format->cpp[0]);
 		ret = -EINVAL;
@@ -448,7 +448,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 		size = pitch * mode_cmd->height / vsub;
 
 		if (size > omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i]) {
-			dev_err(dev->dev,
+			dev_dbg(dev->dev,
 				"provided buffer object is too small! %d < %d\n",
 				bos[i]->size - mode_cmd->offsets[i], size);
 			ret = -EINVAL;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 06/22] drm: omapdrm: Handle FIFO underflow IRQs internally
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (4 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 05/22] drm: omapdrm: fb: Turn framebuffer creation error messages into debug Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14 10:22   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 07/22] drm: omapdrm: Handle CRTC error IRQs directly Laurent Pinchart
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

As the FIFO underflow IRQ handler just prints an error message to the
kernel log, simplify the code by not registering one IRQ handler per
plane but print the messages directly from the main IRQ handler.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
Changes since v3:

- Renamed error_irqs to omap_underflow_irqs

Changes since v1:

- Only register error IRQs that exist on the HW
---
 drivers/gpu/drm/omapdrm/omap_drv.c   |  4 +--
 drivers/gpu/drm/omapdrm/omap_drv.h   |  2 +-
 drivers/gpu/drm/omapdrm/omap_irq.c   | 67 ++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/omapdrm/omap_plane.c | 24 -------------
 4 files changed, 67 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index fdc83cbcde61..6faba13c8e41 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -315,8 +315,6 @@ static int omap_modeset_init(struct drm_device *dev)
 
 	drm_mode_config_init(dev);
 
-	omap_drm_irq_install(dev);
-
 	ret = omap_modeset_init_properties(dev);
 	if (ret < 0)
 		return ret;
@@ -489,6 +487,8 @@ static int omap_modeset_init(struct drm_device *dev)
 
 	drm_mode_config_reset(dev);
 
+	omap_drm_irq_install(dev);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 919c14d3503c..a3594fa10ef3 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -102,7 +102,7 @@ struct omap_drm_private {
 
 	/* irq handling: */
 	struct list_head irq_list;    /* list of omap_drm_irq */
-	uint32_t vblank_mask;         /* irq bits set for userspace vblank */
+	uint32_t irq_mask;		/* enabled irqs in addition to irq_list */
 	struct omap_drm_irq error_handler;
 
 	/* atomic commit */
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 60e1e8016708..57a2de7e0d7b 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -32,7 +32,7 @@ static void omap_irq_update(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_drm_irq *irq;
-	uint32_t irqmask = priv->vblank_mask;
+	uint32_t irqmask = priv->irq_mask;
 
 	assert_spin_locked(&list_lock);
 
@@ -153,7 +153,7 @@ int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe)
 	DBG("dev=%p, crtc=%u", dev, pipe);
 
 	spin_lock_irqsave(&list_lock, flags);
-	priv->vblank_mask |= pipe2vbl(crtc);
+	priv->irq_mask |= pipe2vbl(crtc);
 	omap_irq_update(dev);
 	spin_unlock_irqrestore(&list_lock, flags);
 
@@ -178,11 +178,52 @@ void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe)
 	DBG("dev=%p, crtc=%u", dev, pipe);
 
 	spin_lock_irqsave(&list_lock, flags);
-	priv->vblank_mask &= ~pipe2vbl(crtc);
+	priv->irq_mask &= ~pipe2vbl(crtc);
 	omap_irq_update(dev);
 	spin_unlock_irqrestore(&list_lock, flags);
 }
 
+static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
+				    u32 irqstatus)
+{
+	static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
+				      DEFAULT_RATELIMIT_BURST);
+	static const struct {
+		const char *name;
+		u32 mask;
+	} sources[] = {
+		{ "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW },
+		{ "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW },
+		{ "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW },
+		{ "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW },
+	};
+
+	const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW
+		       | DISPC_IRQ_VID1_FIFO_UNDERFLOW
+		       | DISPC_IRQ_VID2_FIFO_UNDERFLOW
+		       | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
+	unsigned int i;
+
+	spin_lock(&list_lock);
+	irqstatus &= priv->irq_mask & mask;
+	spin_unlock(&list_lock);
+
+	if (!irqstatus)
+		return;
+
+	if (!__ratelimit(&_rs))
+		return;
+
+	DRM_ERROR("FIFO underflow on ");
+
+	for (i = 0; i < ARRAY_SIZE(sources); ++i) {
+		if (sources[i].mask & irqstatus)
+			pr_cont("%s ", sources[i].name);
+	}
+
+	pr_cont("(0x%08x)\n", irqstatus);
+}
+
 static irqreturn_t omap_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -205,6 +246,8 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 			drm_handle_vblank(dev, id);
 	}
 
+	omap_irq_fifo_underflow(priv, irqstatus);
+
 	spin_lock_irqsave(&list_lock, flags);
 	list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
 		if (handler->irqmask & irqstatus) {
@@ -218,6 +261,13 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
+static const u32 omap_underflow_irqs[] = {
+	[OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
+	[OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
+	[OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
+	[OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
+};
+
 /*
  * We need a special version, instead of just using drm_irq_install(),
  * because we need to register the irq via omapdss.  Once omapdss and
@@ -229,10 +279,21 @@ int omap_drm_irq_install(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_drm_irq *error_handler = &priv->error_handler;
+	unsigned int max_planes;
+	unsigned int i;
 	int ret;
 
 	INIT_LIST_HEAD(&priv->irq_list);
 
+	priv->irq_mask = 0;
+
+	max_planes = min(ARRAY_SIZE(priv->planes),
+			 ARRAY_SIZE(omap_underflow_irqs));
+	for (i = 0; i < max_planes; ++i) {
+		if (priv->planes[i])
+			priv->irq_mask |= omap_underflow_irqs[i];
+	}
+
 	dispc_runtime_get();
 	dispc_clear_irqstatus(0xffffffff);
 	dispc_runtime_put();
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 82b2c23d6769..386d90af70f7 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -43,8 +43,6 @@ struct omap_plane {
 
 	uint32_t nformats;
 	uint32_t formats[32];
-
-	struct omap_drm_irq error_irq;
 };
 
 struct omap_plane_state {
@@ -204,8 +202,6 @@ static void omap_plane_destroy(struct drm_plane *plane)
 
 	DBG("%s", omap_plane->name);
 
-	omap_irq_unregister(plane->dev, &omap_plane->error_irq);
-
 	drm_plane_cleanup(plane);
 
 	kfree(omap_plane);
@@ -332,14 +328,6 @@ static const struct drm_plane_funcs omap_plane_funcs = {
 	.atomic_get_property = omap_plane_atomic_get_property,
 };
 
-static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
-{
-	struct omap_plane *omap_plane =
-			container_of(irq, struct omap_plane, error_irq);
-	DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_plane->name,
-		irqstatus);
-}
-
 static const char *plane_names[] = {
 	[OMAP_DSS_GFX] = "gfx",
 	[OMAP_DSS_VIDEO1] = "vid1",
@@ -347,13 +335,6 @@ static const char *plane_names[] = {
 	[OMAP_DSS_VIDEO3] = "vid3",
 };
 
-static const uint32_t error_irqs[] = {
-	[OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
-	[OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
-	[OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
-	[OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
-};
-
 /* initialize plane */
 struct drm_plane *omap_plane_init(struct drm_device *dev,
 		int id, enum drm_plane_type type,
@@ -377,10 +358,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 
 	plane = &omap_plane->base;
 
-	omap_plane->error_irq.irqmask = error_irqs[id];
-	omap_plane->error_irq.irq = omap_plane_error_irq;
-	omap_irq_register(dev, &omap_plane->error_irq);
-
 	ret = drm_universal_plane_init(dev, plane, possible_crtcs,
 				       &omap_plane_funcs, omap_plane->formats,
 				       omap_plane->nformats, type, NULL);
@@ -394,7 +371,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 	return plane;
 
 error:
-	omap_irq_unregister(plane->dev, &omap_plane->error_irq);
 	kfree(omap_plane);
 	return NULL;
 }
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 07/22] drm: omapdrm: Handle CRTC error IRQs directly
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (5 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 06/22] drm: omapdrm: Handle FIFO underflow IRQs internally Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 08/22] drm: omapdrm: Handle OCP error IRQ directly Laurent Pinchart
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Instead of going through a complicated registration mechanism, just
expose the CRTC error IRQ function and call it directly from the main
IRQ handler.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 12 ++----------
 drivers/gpu/drm/omapdrm/omap_drv.h  |  1 +
 drivers/gpu/drm/omapdrm/omap_irq.c  |  8 ++++++++
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 8dea89030e66..ea274143cea0 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -37,7 +37,6 @@ struct omap_crtc {
 	struct videomode vm;
 
 	struct omap_drm_irq vblank_irq;
-	struct omap_drm_irq error_irq;
 
 	bool ignore_digit_sync_lost;
 
@@ -275,10 +274,9 @@ static void omap_crtc_complete_page_flip(struct drm_crtc *crtc)
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus)
 {
-	struct omap_crtc *omap_crtc =
-			container_of(irq, struct omap_crtc, error_irq);
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 
 	if (omap_crtc->ignore_digit_sync_lost) {
 		irqstatus &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
@@ -325,7 +323,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
 	DBG("%s", omap_crtc->name);
 
 	WARN_ON(omap_crtc->vblank_irq.registered);
-	omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
 
 	drm_crtc_cleanup(crtc);
 
@@ -549,11 +546,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 	omap_crtc->vblank_irq.irqmask = pipe2vbl(crtc);
 	omap_crtc->vblank_irq.irq = omap_crtc_vblank_irq;
 
-	omap_crtc->error_irq.irqmask =
-			dispc_mgr_get_sync_lost_irq(channel);
-	omap_crtc->error_irq.irq = omap_crtc_error_irq;
-	omap_irq_register(dev, &omap_crtc->error_irq);
-
 	ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
 					&omap_crtc_funcs, NULL);
 	if (ret < 0) {
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index a3594fa10ef3..0d88c9798df9 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -155,6 +155,7 @@ void omap_crtc_pre_uninit(void);
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, enum omap_channel channel, int id);
 int omap_crtc_wait_pending(struct drm_crtc *crtc);
+void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
 
 struct drm_plane *omap_plane_init(struct drm_device *dev,
 		int id, enum drm_plane_type type,
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 57a2de7e0d7b..58c5efb26766 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -241,9 +241,13 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 
 	for (id = 0; id < priv->num_crtcs; id++) {
 		struct drm_crtc *crtc = priv->crtcs[id];
+		enum omap_channel channel = omap_crtc_channel(crtc);
 
 		if (irqstatus & pipe2vbl(crtc))
 			drm_handle_vblank(dev, id);
+
+		if (irqstatus & dispc_mgr_get_sync_lost_irq(channel))
+			omap_crtc_error_irq(crtc, irqstatus);
 	}
 
 	omap_irq_fifo_underflow(priv, irqstatus);
@@ -279,6 +283,7 @@ int omap_drm_irq_install(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_drm_irq *error_handler = &priv->error_handler;
+	unsigned int num_mgrs = dss_feat_get_num_mgrs();
 	unsigned int max_planes;
 	unsigned int i;
 	int ret;
@@ -294,6 +299,9 @@ int omap_drm_irq_install(struct drm_device *dev)
 			priv->irq_mask |= omap_underflow_irqs[i];
 	}
 
+	for (i = 0; i < num_mgrs; ++i)
+		priv->irq_mask |= dispc_mgr_get_sync_lost_irq(i);
+
 	dispc_runtime_get();
 	dispc_clear_irqstatus(0xffffffff);
 	dispc_runtime_put();
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 08/22] drm: omapdrm: Handle OCP error IRQ directly
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (6 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 07/22] drm: omapdrm: Handle CRTC error IRQs directly Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14 10:24   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 09/22] drm: omapdrm: Replace DSS manager state check with omapdrm CRTC state Laurent Pinchart
                   ` (14 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Instead of going through a complicated registration mechanism, just
call the OCP error IRQ handler directly from the main IRQ handler.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Rename IRQ handler to omap_irq_ocp_error_handler()
- Replace hex error value with "OCP error" message
---
 drivers/gpu/drm/omapdrm/omap_drv.h |  1 -
 drivers/gpu/drm/omapdrm/omap_irq.c | 28 ++++++++++------------------
 2 files changed, 10 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 0d88c9798df9..851629e8704e 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -103,7 +103,6 @@ struct omap_drm_private {
 	/* irq handling: */
 	struct list_head irq_list;    /* list of omap_drm_irq */
 	uint32_t irq_mask;		/* enabled irqs in addition to irq_list */
-	struct omap_drm_irq error_handler;
 
 	/* atomic commit */
 	struct {
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 58c5efb26766..e1925fa6d849 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -21,12 +21,6 @@
 
 static DEFINE_SPINLOCK(list_lock);
 
-static void omap_irq_error_handler(struct omap_drm_irq *irq,
-		uint32_t irqstatus)
-{
-	DRM_ERROR("errors: %08x\n", irqstatus);
-}
-
 /* call with list_lock and dispc runtime held */
 static void omap_irq_update(struct drm_device *dev)
 {
@@ -224,6 +218,14 @@ static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
 	pr_cont("(0x%08x)\n", irqstatus);
 }
 
+static void omap_irq_ocp_error_handler(u32 irqstatus)
+{
+	if (!(irqstatus & DISPC_IRQ_OCP_ERR))
+		return;
+
+	DRM_ERROR("OCP error\n");
+}
+
 static irqreturn_t omap_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -250,6 +252,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 			omap_crtc_error_irq(crtc, irqstatus);
 	}
 
+	omap_irq_ocp_error_handler(irqstatus);
 	omap_irq_fifo_underflow(priv, irqstatus);
 
 	spin_lock_irqsave(&list_lock, flags);
@@ -282,7 +285,6 @@ static const u32 omap_underflow_irqs[] = {
 int omap_drm_irq_install(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
-	struct omap_drm_irq *error_handler = &priv->error_handler;
 	unsigned int num_mgrs = dss_feat_get_num_mgrs();
 	unsigned int max_planes;
 	unsigned int i;
@@ -290,7 +292,7 @@ int omap_drm_irq_install(struct drm_device *dev)
 
 	INIT_LIST_HEAD(&priv->irq_list);
 
-	priv->irq_mask = 0;
+	priv->irq_mask = DISPC_IRQ_OCP_ERR;
 
 	max_planes = min(ARRAY_SIZE(priv->planes),
 			 ARRAY_SIZE(omap_underflow_irqs));
@@ -310,16 +312,6 @@ int omap_drm_irq_install(struct drm_device *dev)
 	if (ret < 0)
 		return ret;
 
-	error_handler->irq = omap_irq_error_handler;
-	error_handler->irqmask = DISPC_IRQ_OCP_ERR;
-
-	/* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think
-	 * we just need to ignore it while enabling tv-out
-	 */
-	error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
-
-	omap_irq_register(dev, error_handler);
-
 	dev->irq_enabled = true;
 
 	return 0;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 09/22] drm: omapdrm: Replace DSS manager state check with omapdrm CRTC state
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (7 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 08/22] drm: omapdrm: Handle OCP error IRQ directly Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14 10:36   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 10/22] drm: omapdrm: Let the DRM core skip plane commit on inactive CRTCs Laurent Pinchart
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Instead of conditioning planes update based on the DSS manager hardware
state, use the enabled field newly added to the omap_crtc structure.
This reduces the dependency from the DRM layer to the DSS layer.

The enabled field is a transitory measure, the implementation should use
the CRTC atomic state instead. However, given that CRTCs are currently
not enabled/disabled through their .enable() and .disable() operations
but through a convoluted code paths starting at the associated encoder
operations, there is not clear guarantee that the atomic state always
matches the hardware state. This will be refactored later, at which
point the enabled field will be removed.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v3:

- Clarify commit message

Changes since v2:

- Use enabled field in struct omap_crtc instead of CRTC atomic state
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index ea274143cea0..42c3b44f9689 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -40,6 +40,7 @@ struct omap_crtc {
 
 	bool ignore_digit_sync_lost;
 
+	bool enabled;
 	bool pending;
 	wait_queue_head_t pending_wait;
 };
@@ -136,6 +137,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
 
 	if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) {
 		dispc_mgr_enable(channel, enable);
+		omap_crtc->enabled = enable;
 		return;
 	}
 
@@ -172,6 +174,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
 	}
 
 	dispc_mgr_enable(channel, enable);
+	omap_crtc->enabled = enable;
 
 	ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
 	if (ret) {
@@ -411,18 +414,19 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 		dispc_mgr_set_gamma(omap_crtc->channel, lut, length);
 	}
 
-	if (dispc_mgr_is_enabled(omap_crtc->channel)) {
+	/* Only flush the CRTC if it is currently enabled. */
+	if (!omap_crtc->enabled)
+		return;
 
-		DBG("%s: GO", omap_crtc->name);
+	DBG("%s: GO", omap_crtc->name);
 
-		rmb();
-		WARN_ON(omap_crtc->pending);
-		omap_crtc->pending = true;
-		wmb();
+	rmb();
+	WARN_ON(omap_crtc->pending);
+	omap_crtc->pending = true;
+	wmb();
 
-		dispc_mgr_go(omap_crtc->channel);
-		omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
-	}
+	dispc_mgr_go(omap_crtc->channel);
+	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
 }
 
 static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc,
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 10/22] drm: omapdrm: Let the DRM core skip plane commit on inactive CRTCs
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (8 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 09/22] drm: omapdrm: Replace DSS manager state check with omapdrm CRTC state Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14 10:43   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 11/22] drm: omapdrm: Check the CRTC software state at enable/disable time Laurent Pinchart
                   ` (12 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The DRM core supports skipping plane update for inactive CRTCs for
hardware that don't need it or can't cope with it. That's our case, and
the driver already skips flushing planes on inactice CRTCs.

We can't remove the check from the driver, as active CRTCs are disabled
at the hardware level when an atomic flush is performed if a mode set is
pending. There's however no need to forward the plane commit calls to
the driver, so use the DRM core infrastructure to skip them with a
detailed comment to explain why the check must still be kept in the
driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v3:

- Reworded commit message
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 8 +++++++-
 drivers/gpu/drm/omapdrm/omap_drv.c  | 3 ++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 42c3b44f9689..2832dbffd873 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -414,7 +414,13 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 		dispc_mgr_set_gamma(omap_crtc->channel, lut, length);
 	}
 
-	/* Only flush the CRTC if it is currently enabled. */
+	/*
+	 * Only flush the CRTC if it is currently enabled. CRTCs that require a
+	 * mode set are disabled prior plane updates and enabled afterwards.
+	 * They are thus not active (regardless of what their CRTC core state
+	 * reports) and the DRM core could thus call this function even though
+	 * the CRTC is currently disabled. Do nothing in that case.
+	 */
 	if (!omap_crtc->enabled)
 		return;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 6faba13c8e41..0a2d461d62cf 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -96,7 +96,8 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
 	dispc_runtime_get();
 
 	drm_atomic_helper_commit_modeset_disables(dev, old_state);
-	drm_atomic_helper_commit_planes(dev, old_state, 0);
+	drm_atomic_helper_commit_planes(dev, old_state,
+					DRM_PLANE_COMMIT_ACTIVE_ONLY);
 	drm_atomic_helper_commit_modeset_enables(dev, old_state);
 
 	omap_atomic_wait_for_completion(dev, old_state);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 11/22] drm: omapdrm: Check the CRTC software state at enable/disable time
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (9 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 10/22] drm: omapdrm: Let the DRM core skip plane commit on inactive CRTCs Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14 14:54   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 12/22] drm: omapdrm: Prevent processing the same event multiple times Laurent Pinchart
                   ` (11 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The omapdrm DSS manager enable/disable operations check the DSS manager
state to avoid double enabling/disabling. Check the CRTC software state
instead to decrease the dependency of the DRM layer to the DSS layer.
The dispc_mgr_is_enabled() function then be turned into a static
function, but needs to be moved up in its compilation unit to avoid a
forward declaration.

Add a WARN_ON to catch double enable or disable that should be prevented
by the DRM core and would be a clear sign of a bug. The warning should
eventually be removed.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v3:

- Replace the hardware state check with a software state check in
  omapdrm instead of moving it to omapdss.
- Added a WARN_ON to catch impossible situations that would be a sign of
  a clear bug
---
 drivers/gpu/drm/omapdrm/dss/dispc.c   | 27 +++++++++++++--------------
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  1 -
 drivers/gpu/drm/omapdrm/omap_crtc.c   |  6 +++---
 3 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
index c839f6456db2..5554b72cf56a 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
@@ -620,6 +620,19 @@ u32 dispc_wb_get_framedone_irq(void)
 	return DISPC_IRQ_FRAMEDONEWB;
 }
 
+void dispc_mgr_enable(enum omap_channel channel, bool enable)
+{
+	mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
+	/* flush posted write */
+	mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
+}
+EXPORT_SYMBOL(dispc_mgr_enable);
+
+static bool dispc_mgr_is_enabled(enum omap_channel channel)
+{
+	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
+}
+
 bool dispc_mgr_go_busy(enum omap_channel channel)
 {
 	return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
@@ -2901,20 +2914,6 @@ enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channe
 }
 EXPORT_SYMBOL(dispc_mgr_get_supported_outputs);
 
-void dispc_mgr_enable(enum omap_channel channel, bool enable)
-{
-	mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
-	/* flush posted write */
-	mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
-}
-EXPORT_SYMBOL(dispc_mgr_enable);
-
-bool dispc_mgr_is_enabled(enum omap_channel channel)
-{
-	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
-}
-EXPORT_SYMBOL(dispc_mgr_is_enabled);
-
 void dispc_wb_enable(bool enable)
 {
 	dispc_ovl_enable(OMAP_DSS_WB, enable);
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index b420dde8c0fb..5b3b961127bd 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -856,7 +856,6 @@ int dispc_runtime_get(void);
 void dispc_runtime_put(void);
 
 void dispc_mgr_enable(enum omap_channel channel, bool enable);
-bool dispc_mgr_is_enabled(enum omap_channel channel);
 u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
 u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
 u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel);
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 2832dbffd873..a0511cd5d380 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -135,15 +135,15 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
 	u32 framedone_irq, vsync_irq;
 	int ret;
 
+	if (WARN_ON(omap_crtc->enabled == enable))
+		return;
+
 	if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) {
 		dispc_mgr_enable(channel, enable);
 		omap_crtc->enabled = enable;
 		return;
 	}
 
-	if (dispc_mgr_is_enabled(channel) == enable)
-		return;
-
 	if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) {
 		/*
 		 * Digit output produces some sync lost interrupts during the
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 12/22] drm: omapdrm: Prevent processing the same event multiple times
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (10 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 11/22] drm: omapdrm: Check the CRTC software state at enable/disable time Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-15 12:20   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 13/22] drm: omapdrm: Use a spinlock to protect the CRTC pending flag Laurent Pinchart
                   ` (10 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The vblank interrupt is disabled after one occurrence, preventing the
atomic update event from being processed twice. However, this also
prevents the software frame counter from being updated correctly that
would require vblank interrupts to be kept enabled while the CRTC is
active.

In preparation for vblank interrupt fixes, make sure that the atomic
update event will be processed once only when the vblank interrupt will
be kept enabled.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v3:

- Don't release and reacquire the spinlock for just one return
- Remove unneeded (and unbalanced) drm_crtc_vblank_get()
- Store the event in the atomic flush handler to avoid race condition
- Use spin_lock_irq instead of spin_lock_irsave in flush handler
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index a0511cd5d380..7b67ecb02b74 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -43,6 +43,7 @@ struct omap_crtc {
 	bool enabled;
 	bool pending;
 	wait_queue_head_t pending_wait;
+	struct drm_pending_vblank_event *event;
 };
 
 /* -----------------------------------------------------------------------------
@@ -263,17 +264,17 @@ static const struct dss_mgr_ops mgr_ops = {
 
 static void omap_crtc_complete_page_flip(struct drm_crtc *crtc)
 {
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 	struct drm_pending_vblank_event *event;
 	struct drm_device *dev = crtc->dev;
 	unsigned long flags;
 
-	event = crtc->state->event;
-
-	if (!event)
-		return;
-
 	spin_lock_irqsave(&dev->event_lock, flags);
-	drm_crtc_send_vblank_event(crtc, event);
+	event = omap_crtc->event;
+	omap_crtc->event = NULL;
+
+	if (event)
+		drm_crtc_send_vblank_event(crtc, event);
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
@@ -390,12 +391,12 @@ static int omap_crtc_atomic_check(struct drm_crtc *crtc,
 }
 
 static void omap_crtc_atomic_begin(struct drm_crtc *crtc,
-                                  struct drm_crtc_state *old_crtc_state)
+				   struct drm_crtc_state *old_crtc_state)
 {
 }
 
 static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
-                                  struct drm_crtc_state *old_crtc_state)
+				   struct drm_crtc_state *old_crtc_state)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 
@@ -431,6 +432,12 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 	omap_crtc->pending = true;
 	wmb();
 
+	if (crtc->state->event) {
+		spin_lock_irq(&crtc->dev->event_lock);
+		omap_crtc->event = crtc->state->event;
+		spin_unlock_irq(&crtc->dev->event_lock);
+	}
+
 	dispc_mgr_go(omap_crtc->channel);
 	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
 }
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 13/22] drm: omapdrm: Use a spinlock to protect the CRTC pending flag
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (11 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 12/22] drm: omapdrm: Prevent processing the same event multiple times Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active Laurent Pinchart
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The CRTC pending flag will need to be accessed atomically in the vblank
interrupt handler, memory barriers won't be enough to protect it. Use a
spinlock instead.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---

Changes since v3:

- Reworded commit message
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 7b67ecb02b74..827ac46a6d5e 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -69,6 +69,19 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
 	return omap_crtc->channel;
 }
 
+static bool omap_crtc_is_pending(struct drm_crtc *crtc)
+{
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	unsigned long flags;
+	bool pending;
+
+	spin_lock_irqsave(&crtc->dev->event_lock, flags);
+	pending = omap_crtc->pending;
+	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+
+	return pending;
+}
+
 int omap_crtc_wait_pending(struct drm_crtc *crtc)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
@@ -78,7 +91,7 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc)
 	 * a single frame refresh even on slower displays.
 	 */
 	return wait_event_timeout(omap_crtc->pending_wait,
-				  !omap_crtc->pending,
+				  !omap_crtc_is_pending(crtc),
 				  msecs_to_jiffies(250));
 }
 
@@ -296,6 +309,7 @@ static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
 	struct omap_crtc *omap_crtc =
 			container_of(irq, struct omap_crtc, vblank_irq);
 	struct drm_device *dev = omap_crtc->base.dev;
+	struct drm_crtc *crtc = &omap_crtc->base;
 
 	if (dispc_mgr_go_busy(omap_crtc->channel))
 		return;
@@ -304,10 +318,10 @@ static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
 
 	__omap_irq_unregister(dev, &omap_crtc->vblank_irq);
 
-	rmb();
+	spin_lock(&crtc->dev->event_lock);
 	WARN_ON(!omap_crtc->pending);
 	omap_crtc->pending = false;
-	wmb();
+	spin_unlock(&crtc->dev->event_lock);
 
 	/* wake up userspace */
 	omap_crtc_complete_page_flip(&omap_crtc->base);
@@ -339,10 +353,10 @@ static void omap_crtc_enable(struct drm_crtc *crtc)
 
 	DBG("%s", omap_crtc->name);
 
-	rmb();
+	spin_lock_irq(&crtc->dev->event_lock);
 	WARN_ON(omap_crtc->pending);
 	omap_crtc->pending = true;
-	wmb();
+	spin_unlock_irq(&crtc->dev->event_lock);
 
 	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
 
@@ -427,16 +441,13 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DBG("%s: GO", omap_crtc->name);
 
-	rmb();
+	spin_lock_irq(&crtc->dev->event_lock);
 	WARN_ON(omap_crtc->pending);
 	omap_crtc->pending = true;
-	wmb();
 
-	if (crtc->state->event) {
-		spin_lock_irq(&crtc->dev->event_lock);
+	if (crtc->state->event)
 		omap_crtc->event = crtc->state->event;
-		spin_unlock_irq(&crtc->dev->event_lock);
-	}
+	spin_unlock_irq(&crtc->dev->event_lock);
 
 	dispc_mgr_go(omap_crtc->channel);
 	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (12 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 13/22] drm: omapdrm: Use a spinlock to protect the CRTC pending flag Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-15 12:52   ` Tomi Valkeinen
  2016-12-18  2:12   ` [PATCH v4.1 " Laurent Pinchart
  2016-12-14  0:27 ` [PATCH v4 15/22] drm: omapdrm: Don't expose the omap_irq_(un)register() functions Laurent Pinchart
                   ` (8 subsequent siblings)
  22 siblings, 2 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Instead of going through a complicated private IRQ registration
mechanism, handle the vblank interrupt activation with the standard
drm_crtc_vblank_get() and drm_crtc_vblank_put() mechanism. This will let
the DRM core keep the vblank interrupt enabled as long as needed to
update the frame counter.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 38 ++++++++++++++-----------------------
 drivers/gpu/drm/omapdrm/omap_drv.h  |  1 +
 drivers/gpu/drm/omapdrm/omap_irq.c  |  4 +++-
 3 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 827ac46a6d5e..1f5372042706 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -36,8 +36,6 @@ struct omap_crtc {
 
 	struct videomode vm;
 
-	struct omap_drm_irq vblank_irq;
-
 	bool ignore_digit_sync_lost;
 
 	bool enabled;
@@ -304,25 +302,24 @@ void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus)
 	DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus);
 }
 
-static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+void omap_crtc_vblank_irq(struct drm_crtc *crtc)
 {
-	struct omap_crtc *omap_crtc =
-			container_of(irq, struct omap_crtc, vblank_irq);
-	struct drm_device *dev = omap_crtc->base.dev;
-	struct drm_crtc *crtc = &omap_crtc->base;
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	bool pending;
 
 	if (dispc_mgr_go_busy(omap_crtc->channel))
 		return;
 
 	DBG("%s: apply done", omap_crtc->name);
 
-	__omap_irq_unregister(dev, &omap_crtc->vblank_irq);
-
 	spin_lock(&crtc->dev->event_lock);
-	WARN_ON(!omap_crtc->pending);
+	pending = omap_crtc->pending;
 	omap_crtc->pending = false;
 	spin_unlock(&crtc->dev->event_lock);
 
+	if (pending)
+		drm_crtc_vblank_put(crtc);
+
 	/* wake up userspace */
 	omap_crtc_complete_page_flip(&omap_crtc->base);
 
@@ -340,8 +337,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
 
 	DBG("%s", omap_crtc->name);
 
-	WARN_ON(omap_crtc->vblank_irq.registered);
-
 	drm_crtc_cleanup(crtc);
 
 	kfree(omap_crtc);
@@ -353,14 +348,13 @@ static void omap_crtc_enable(struct drm_crtc *crtc)
 
 	DBG("%s", omap_crtc->name);
 
+	drm_crtc_vblank_on(crtc);
+	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
 	spin_lock_irq(&crtc->dev->event_lock);
 	WARN_ON(omap_crtc->pending);
 	omap_crtc->pending = true;
 	spin_unlock_irq(&crtc->dev->event_lock);
-
-	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
-
-	drm_crtc_vblank_on(crtc);
 }
 
 static void omap_crtc_disable(struct drm_crtc *crtc)
@@ -414,8 +408,6 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 
-	WARN_ON(omap_crtc->vblank_irq.registered);
-
 	if (crtc->state->color_mgmt_changed) {
 		struct drm_color_lut *lut = NULL;
 		uint length = 0;
@@ -441,6 +433,10 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DBG("%s: GO", omap_crtc->name);
 
+	dispc_mgr_go(omap_crtc->channel);
+
+	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
 	spin_lock_irq(&crtc->dev->event_lock);
 	WARN_ON(omap_crtc->pending);
 	omap_crtc->pending = true;
@@ -448,9 +444,6 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 	if (crtc->state->event)
 		omap_crtc->event = crtc->state->event;
 	spin_unlock_irq(&crtc->dev->event_lock);
-
-	dispc_mgr_go(omap_crtc->channel);
-	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
 }
 
 static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc,
@@ -571,9 +564,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 	omap_crtc->channel = channel;
 	omap_crtc->name = channel_names[channel];
 
-	omap_crtc->vblank_irq.irqmask = pipe2vbl(crtc);
-	omap_crtc->vblank_irq.irq = omap_crtc_vblank_irq;
-
 	ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
 					&omap_crtc_funcs, NULL);
 	if (ret < 0) {
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 851629e8704e..9437acc1c541 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -155,6 +155,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, enum omap_channel channel, int id);
 int omap_crtc_wait_pending(struct drm_crtc *crtc);
 void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
+void omap_crtc_vblank_irq(struct drm_crtc *crtc);
 
 struct drm_plane *omap_plane_init(struct drm_device *dev,
 		int id, enum drm_plane_type type,
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index e1925fa6d849..1c826907dead 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -245,8 +245,10 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 		struct drm_crtc *crtc = priv->crtcs[id];
 		enum omap_channel channel = omap_crtc_channel(crtc);
 
-		if (irqstatus & pipe2vbl(crtc))
+		if (irqstatus & pipe2vbl(crtc)) {
 			drm_handle_vblank(dev, id);
+			omap_crtc_vblank_irq(crtc);
+		}
 
 		if (irqstatus & dispc_mgr_get_sync_lost_irq(channel))
 			omap_crtc_error_irq(crtc, irqstatus);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 15/22] drm: omapdrm: Don't expose the omap_irq_(un)register() functions
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (13 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-15 12:56   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 16/22] drm: omapdrm: Remove unused parameter from omap_drm_irq handler Laurent Pinchart
                   ` (7 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The IRQ registration functions are not used outside of their compilation
unit, make them static. As the __omap_irq_(un)register() functions are
only called by their omap_irq_(un)register() counterparts, merge them
together.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Split the omap_drm_irq irqstatus parameter removal change out
---
 drivers/gpu/drm/omapdrm/omap_drv.h |  4 ----
 drivers/gpu/drm/omapdrm/omap_irq.c | 23 +++++------------------
 2 files changed, 5 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 9437acc1c541..56159992ba18 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -127,10 +127,6 @@ int omap_gem_resume(struct device *dev);
 
 int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe);
 void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe);
-void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
-void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
-void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
-void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
 void omap_drm_irq_uninstall(struct drm_device *dev);
 int omap_drm_irq_install(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 1c826907dead..2fda60105b3c 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -39,11 +39,12 @@ static void omap_irq_update(struct drm_device *dev)
 	dispc_read_irqenable();        /* flush posted write */
 }
 
-void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
+static void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	unsigned long flags;
 
+	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 
 	if (!WARN_ON(irq->registered)) {
@@ -53,21 +54,15 @@ void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 	}
 
 	spin_unlock_irqrestore(&list_lock, flags);
-}
-
-void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
-{
-	dispc_runtime_get();
-
-	__omap_irq_register(dev, irq);
-
 	dispc_runtime_put();
 }
 
-void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
+static void omap_irq_unregister(struct drm_device *dev,
+				struct omap_drm_irq *irq)
 {
 	unsigned long flags;
 
+	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 
 	if (!WARN_ON(!irq->registered)) {
@@ -77,14 +72,6 @@ void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
 	}
 
 	spin_unlock_irqrestore(&list_lock, flags);
-}
-
-void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
-{
-	dispc_runtime_get();
-
-	__omap_irq_unregister(dev, irq);
-
 	dispc_runtime_put();
 }
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 16/22] drm: omapdrm: Remove unused parameter from omap_drm_irq handler
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (14 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 15/22] drm: omapdrm: Don't expose the omap_irq_(un)register() functions Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-15 12:57   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 17/22] drm: omapdrm: Don't call DISPC power handling in IRQ wait functions Laurent Pinchart
                   ` (6 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The only omap_drm_irq handler doesn't use the irqstatus parameter passed
to the function. Remove it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- New patch
---
 drivers/gpu/drm/omapdrm/omap_drv.h | 2 +-
 drivers/gpu/drm/omapdrm/omap_irq.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 56159992ba18..7868feb604fc 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -58,7 +58,7 @@ struct omap_drm_irq {
 	struct list_head node;
 	uint32_t irqmask;
 	bool registered;
-	void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus);
+	void (*irq)(struct omap_drm_irq *irq);
 };
 
 /* For KMS code that needs to wait for a certain # of IRQs:
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 2fda60105b3c..5b22d297f1ea 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -82,7 +82,7 @@ struct omap_irq_wait {
 
 static DECLARE_WAIT_QUEUE_HEAD(wait_event);
 
-static void wait_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+static void wait_irq(struct omap_drm_irq *irq)
 {
 	struct omap_irq_wait *wait =
 			container_of(irq, struct omap_irq_wait, irq);
@@ -248,7 +248,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 	list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
 		if (handler->irqmask & irqstatus) {
 			spin_unlock_irqrestore(&list_lock, flags);
-			handler->irq(handler, handler->irqmask & irqstatus);
+			handler->irq(handler);
 			spin_lock_irqsave(&list_lock, flags);
 		}
 	}
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 17/22] drm: omapdrm: Don't call DISPC power handling in IRQ wait functions
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (15 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 16/22] drm: omapdrm: Remove unused parameter from omap_drm_irq handler Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-15 13:00   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 18/22] drm: omapdrm: Inline the pipe2vbl function Laurent Pinchart
                   ` (5 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The IRQ wait functions are called from the DSS enable and disable
operations only, where the DISPC is guaranteed to be enabled. There's no
need for manual DISPC power management there.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_irq.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 5b22d297f1ea..d5c73c534586 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -44,7 +44,6 @@ static void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 	struct omap_drm_private *priv = dev->dev_private;
 	unsigned long flags;
 
-	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 
 	if (!WARN_ON(irq->registered)) {
@@ -54,7 +53,6 @@ static void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 	}
 
 	spin_unlock_irqrestore(&list_lock, flags);
-	dispc_runtime_put();
 }
 
 static void omap_irq_unregister(struct drm_device *dev,
@@ -62,7 +60,6 @@ static void omap_irq_unregister(struct drm_device *dev,
 {
 	unsigned long flags;
 
-	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 
 	if (!WARN_ON(!irq->registered)) {
@@ -72,7 +69,6 @@ static void omap_irq_unregister(struct drm_device *dev,
 	}
 
 	spin_unlock_irqrestore(&list_lock, flags);
-	dispc_runtime_put();
 }
 
 struct omap_irq_wait {
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 18/22] drm: omapdrm: Inline the pipe2vbl function
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (16 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 17/22] drm: omapdrm: Don't call DISPC power handling in IRQ wait functions Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-14 10:25   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 19/22] drm: omapdrm: Simplify IRQ wait implementation Laurent Pinchart
                   ` (4 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The function is only used in omap_irq.c and is just a wrapper around
dispc_mgr_get_vsync_irq(). Remove it and call the dispc function
directly.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v3:

- Removed the pipe2vbl function completely
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 7 -------
 drivers/gpu/drm/omapdrm/omap_drv.h  | 1 -
 drivers/gpu/drm/omapdrm/omap_irq.c  | 6 +++---
 3 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 1f5372042706..3bdfb8719669 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -48,13 +48,6 @@ struct omap_crtc {
  * Helper Functions
  */
 
-uint32_t pipe2vbl(struct drm_crtc *crtc)
-{
-	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-
-	return dispc_mgr_get_vsync_irq(omap_crtc->channel);
-}
-
 struct videomode *omap_crtc_timings(struct drm_crtc *crtc)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 7868feb604fc..dad7d6161563 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -230,7 +230,6 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
 		struct dma_buf *buffer);
 
 /* map crtc to vblank mask */
-uint32_t pipe2vbl(struct drm_crtc *crtc);
 struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder);
 
 #endif /* __OMAP_DRV_H__ */
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index d5c73c534586..1982759a1c27 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -130,7 +130,7 @@ int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe)
 	DBG("dev=%p, crtc=%u", dev, pipe);
 
 	spin_lock_irqsave(&list_lock, flags);
-	priv->irq_mask |= pipe2vbl(crtc);
+	priv->irq_mask |= dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc));
 	omap_irq_update(dev);
 	spin_unlock_irqrestore(&list_lock, flags);
 
@@ -155,7 +155,7 @@ void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe)
 	DBG("dev=%p, crtc=%u", dev, pipe);
 
 	spin_lock_irqsave(&list_lock, flags);
-	priv->irq_mask &= ~pipe2vbl(crtc);
+	priv->irq_mask &= ~dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc));
 	omap_irq_update(dev);
 	spin_unlock_irqrestore(&list_lock, flags);
 }
@@ -228,7 +228,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 		struct drm_crtc *crtc = priv->crtcs[id];
 		enum omap_channel channel = omap_crtc_channel(crtc);
 
-		if (irqstatus & pipe2vbl(crtc)) {
+		if (irqstatus & dispc_mgr_get_vsync_irq(channel)) {
 			drm_handle_vblank(dev, id);
 			omap_crtc_vblank_irq(crtc);
 		}
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 19/22] drm: omapdrm: Simplify IRQ wait implementation
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (17 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 18/22] drm: omapdrm: Inline the pipe2vbl function Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-16 12:24   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 20/22] drm: omapdrm: Remove global variables Laurent Pinchart
                   ` (3 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Now that the IRQ list is used for IRQ wait only we can merge
omap_drm_irq and omap_irq_wait and simplify the implementation.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_drv.h | 17 +------
 drivers/gpu/drm/omapdrm/omap_irq.c | 94 ++++++++++++++------------------------
 2 files changed, 37 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index dad7d6161563..8ef7e8963bd9 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -48,19 +48,6 @@ struct omap_drm_window {
 	uint32_t src_w, src_h;
 };
 
-/* For transiently registering for different DSS irqs that various parts
- * of the KMS code need during setup/configuration.  We these are not
- * necessarily the same as what drm_vblank_get/put() are requesting, and
- * the hysteresis in drm_vblank_put() is not necessarily desirable for
- * internal housekeeping related irq usage.
- */
-struct omap_drm_irq {
-	struct list_head node;
-	uint32_t irqmask;
-	bool registered;
-	void (*irq)(struct omap_drm_irq *irq);
-};
-
 /* For KMS code that needs to wait for a certain # of IRQs:
  */
 struct omap_irq_wait;
@@ -101,8 +88,8 @@ struct omap_drm_private {
 	struct drm_property *zorder_prop;
 
 	/* irq handling: */
-	struct list_head irq_list;    /* list of omap_drm_irq */
-	uint32_t irq_mask;		/* enabled irqs in addition to irq_list */
+	struct list_head wait_list;     /* list of omap_irq_wait */
+	uint32_t irq_mask;		/* enabled irqs in addition to wait_list */
 
 	/* atomic commit */
 	struct {
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 1982759a1c27..f9510c13e1a2 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -21,17 +21,23 @@
 
 static DEFINE_SPINLOCK(list_lock);
 
+struct omap_irq_wait {
+	struct list_head node;
+	uint32_t irqmask;
+	int count;
+};
+
 /* call with list_lock and dispc runtime held */
 static void omap_irq_update(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
-	struct omap_drm_irq *irq;
+	struct omap_irq_wait *wait;
 	uint32_t irqmask = priv->irq_mask;
 
 	assert_spin_locked(&list_lock);
 
-	list_for_each_entry(irq, &priv->irq_list, node)
-		irqmask |= irq->irqmask;
+	list_for_each_entry(wait, &priv->wait_list, node)
+		irqmask |= wait->irqmask;
 
 	DBG("irqmask=%08x", irqmask);
 
@@ -39,61 +45,29 @@ static void omap_irq_update(struct drm_device *dev)
 	dispc_read_irqenable();        /* flush posted write */
 }
 
-static void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
-{
-	struct omap_drm_private *priv = dev->dev_private;
-	unsigned long flags;
-
-	spin_lock_irqsave(&list_lock, flags);
-
-	if (!WARN_ON(irq->registered)) {
-		irq->registered = true;
-		list_add(&irq->node, &priv->irq_list);
-		omap_irq_update(dev);
-	}
-
-	spin_unlock_irqrestore(&list_lock, flags);
-}
-
-static void omap_irq_unregister(struct drm_device *dev,
-				struct omap_drm_irq *irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&list_lock, flags);
-
-	if (!WARN_ON(!irq->registered)) {
-		irq->registered = false;
-		list_del(&irq->node);
-		omap_irq_update(dev);
-	}
-
-	spin_unlock_irqrestore(&list_lock, flags);
-}
-
-struct omap_irq_wait {
-	struct omap_drm_irq irq;
-	int count;
-};
-
 static DECLARE_WAIT_QUEUE_HEAD(wait_event);
 
-static void wait_irq(struct omap_drm_irq *irq)
+static void omap_irq_wait_irq(struct omap_irq_wait *wait)
 {
-	struct omap_irq_wait *wait =
-			container_of(irq, struct omap_irq_wait, irq);
 	wait->count--;
-	wake_up_all(&wait_event);
+	wake_up(&wait_event);
 }
 
 struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
 		uint32_t irqmask, int count)
 {
+	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
-	wait->irq.irq = wait_irq;
-	wait->irq.irqmask = irqmask;
+	unsigned long flags;
+
+	wait->irqmask = irqmask;
 	wait->count = count;
-	omap_irq_register(dev, &wait->irq);
+
+	spin_lock_irqsave(&list_lock, flags);
+	list_add(&wait->node, &priv->wait_list);
+	omap_irq_update(dev);
+	spin_unlock_irqrestore(&list_lock, flags);
+
 	return wait;
 }
 
@@ -101,11 +75,16 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
 		unsigned long timeout)
 {
 	int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout);
-	omap_irq_unregister(dev, &wait->irq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&list_lock, flags);
+	list_del(&wait->node);
+	omap_irq_update(dev);
+	spin_unlock_irqrestore(&list_lock, flags);
+
 	kfree(wait);
-	if (ret == 0)
-		return -1;
-	return 0;
+
+	return ret == 0 ? -1 : 0;
 }
 
 /**
@@ -213,7 +192,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	struct omap_drm_private *priv = dev->dev_private;
-	struct omap_drm_irq *handler, *n;
+	struct omap_irq_wait *wait, *n;
 	unsigned long flags;
 	unsigned int id;
 	u32 irqstatus;
@@ -241,12 +220,9 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 	omap_irq_fifo_underflow(priv, irqstatus);
 
 	spin_lock_irqsave(&list_lock, flags);
-	list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
-		if (handler->irqmask & irqstatus) {
-			spin_unlock_irqrestore(&list_lock, flags);
-			handler->irq(handler);
-			spin_lock_irqsave(&list_lock, flags);
-		}
+	list_for_each_entry_safe(wait, n, &priv->wait_list, node) {
+		if (wait->irqmask & irqstatus)
+			omap_irq_wait_irq(wait);
 	}
 	spin_unlock_irqrestore(&list_lock, flags);
 
@@ -275,7 +251,7 @@ int omap_drm_irq_install(struct drm_device *dev)
 	unsigned int i;
 	int ret;
 
-	INIT_LIST_HEAD(&priv->irq_list);
+	INIT_LIST_HEAD(&priv->wait_list);
 
 	priv->irq_mask = DISPC_IRQ_OCP_ERR;
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 20/22] drm: omapdrm: Remove global variables
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (18 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 19/22] drm: omapdrm: Simplify IRQ wait implementation Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-16 12:31   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 21/22] drm: omapdrm: Use sizeof(*var) instead of sizeof(type) for structures Laurent Pinchart
                   ` (2 subsequent siblings)
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Move the list of pending IRQ wait instances to the omap_drm_private
structure and the wait queue head to the IRQ wait structure.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_drv.h |  3 ++-
 drivers/gpu/drm/omapdrm/omap_irq.c | 42 ++++++++++++++++++++------------------
 2 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 8ef7e8963bd9..b20377efd01b 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -88,7 +88,8 @@ struct omap_drm_private {
 	struct drm_property *zorder_prop;
 
 	/* irq handling: */
-	struct list_head wait_list;     /* list of omap_irq_wait */
+	spinlock_t wait_lock;		/* protects the wait_list */
+	struct list_head wait_list;	/* list of omap_irq_wait */
 	uint32_t irq_mask;		/* enabled irqs in addition to wait_list */
 
 	/* atomic commit */
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index f9510c13e1a2..7555b62f6c53 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -19,22 +19,21 @@
 
 #include "omap_drv.h"
 
-static DEFINE_SPINLOCK(list_lock);
-
 struct omap_irq_wait {
 	struct list_head node;
+	wait_queue_head_t wq;
 	uint32_t irqmask;
 	int count;
 };
 
-/* call with list_lock and dispc runtime held */
+/* call with wait_lock and dispc runtime held */
 static void omap_irq_update(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_irq_wait *wait;
 	uint32_t irqmask = priv->irq_mask;
 
-	assert_spin_locked(&list_lock);
+	assert_spin_locked(&priv->wait_lock);
 
 	list_for_each_entry(wait, &priv->wait_list, node)
 		irqmask |= wait->irqmask;
@@ -45,12 +44,10 @@ static void omap_irq_update(struct drm_device *dev)
 	dispc_read_irqenable();        /* flush posted write */
 }
 
-static DECLARE_WAIT_QUEUE_HEAD(wait_event);
-
 static void omap_irq_wait_irq(struct omap_irq_wait *wait)
 {
 	wait->count--;
-	wake_up(&wait_event);
+	wake_up(&wait->wq);
 }
 
 struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
@@ -60,13 +57,14 @@ struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
 	struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
 	unsigned long flags;
 
+	init_waitqueue_head(&wait->wq);
 	wait->irqmask = irqmask;
 	wait->count = count;
 
-	spin_lock_irqsave(&list_lock, flags);
+	spin_lock_irqsave(&priv->wait_lock, flags);
 	list_add(&wait->node, &priv->wait_list);
 	omap_irq_update(dev);
-	spin_unlock_irqrestore(&list_lock, flags);
+	spin_unlock_irqrestore(&priv->wait_lock, flags);
 
 	return wait;
 }
@@ -74,13 +72,16 @@ struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
 int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
 		unsigned long timeout)
 {
-	int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout);
+	struct omap_drm_private *priv = dev->dev_private;
 	unsigned long flags;
+	int ret;
+
+	ret = wait_event_timeout(wait->wq, (wait->count <= 0), timeout);
 
-	spin_lock_irqsave(&list_lock, flags);
+	spin_lock_irqsave(&priv->wait_lock, flags);
 	list_del(&wait->node);
 	omap_irq_update(dev);
-	spin_unlock_irqrestore(&list_lock, flags);
+	spin_unlock_irqrestore(&priv->wait_lock, flags);
 
 	kfree(wait);
 
@@ -108,10 +109,10 @@ int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe)
 
 	DBG("dev=%p, crtc=%u", dev, pipe);
 
-	spin_lock_irqsave(&list_lock, flags);
+	spin_lock_irqsave(&priv->wait_lock, flags);
 	priv->irq_mask |= dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc));
 	omap_irq_update(dev);
-	spin_unlock_irqrestore(&list_lock, flags);
+	spin_unlock_irqrestore(&priv->wait_lock, flags);
 
 	return 0;
 }
@@ -133,10 +134,10 @@ void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe)
 
 	DBG("dev=%p, crtc=%u", dev, pipe);
 
-	spin_lock_irqsave(&list_lock, flags);
+	spin_lock_irqsave(&priv->wait_lock, flags);
 	priv->irq_mask &= ~dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc));
 	omap_irq_update(dev);
-	spin_unlock_irqrestore(&list_lock, flags);
+	spin_unlock_irqrestore(&priv->wait_lock, flags);
 }
 
 static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
@@ -160,9 +161,9 @@ static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
 		       | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
 	unsigned int i;
 
-	spin_lock(&list_lock);
+	spin_lock(&priv->wait_lock);
 	irqstatus &= priv->irq_mask & mask;
-	spin_unlock(&list_lock);
+	spin_unlock(&priv->wait_lock);
 
 	if (!irqstatus)
 		return;
@@ -219,12 +220,12 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 	omap_irq_ocp_error_handler(irqstatus);
 	omap_irq_fifo_underflow(priv, irqstatus);
 
-	spin_lock_irqsave(&list_lock, flags);
+	spin_lock_irqsave(&priv->wait_lock, flags);
 	list_for_each_entry_safe(wait, n, &priv->wait_list, node) {
 		if (wait->irqmask & irqstatus)
 			omap_irq_wait_irq(wait);
 	}
-	spin_unlock_irqrestore(&list_lock, flags);
+	spin_unlock_irqrestore(&priv->wait_lock, flags);
 
 	return IRQ_HANDLED;
 }
@@ -251,6 +252,7 @@ int omap_drm_irq_install(struct drm_device *dev)
 	unsigned int i;
 	int ret;
 
+	spin_lock_init(&priv->wait_lock);
 	INIT_LIST_HEAD(&priv->wait_list);
 
 	priv->irq_mask = DISPC_IRQ_OCP_ERR;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 21/22] drm: omapdrm: Use sizeof(*var) instead of sizeof(type) for structures
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (19 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 20/22] drm: omapdrm: Remove global variables Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-15 13:02   ` Tomi Valkeinen
  2016-12-14  0:27 ` [PATCH v4 22/22] drm: omapdrm: Perform initialization/cleanup at probe/remove time Laurent Pinchart
  2016-12-14  8:48 ` [PATCH v4 00/22] OMAP DRM fixes and improvements Tomi Valkeinen
  22 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

By linking the sizeof to a variable type the code will be less prone to
bugs due to future type changes of variables.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c | 3 +--
 drivers/gpu/drm/omapdrm/omap_connector.c        | 4 ++--
 drivers/gpu/drm/omapdrm/omap_dmm_tiler.c        | 4 ++--
 drivers/gpu/drm/omapdrm/omap_encoder.c          | 2 +-
 5 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
index dc026a843712..a2bb855a2851 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
@@ -1253,7 +1253,7 @@ static int dsicm_probe(struct platform_device *pdev)
 	dsicm_hw_reset(ddata);
 
 	if (ddata->use_dsi_backlight) {
-		memset(&props, 0, sizeof(struct backlight_properties));
+		memset(&props, 0, sizeof(props));
 		props.max_brightness = 255;
 
 		props.type = BACKLIGHT_RAW;
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
index 136d30484d02..bf626acae271 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
@@ -119,8 +119,7 @@ static void __init omapdss_omapify_node(struct device_node *node)
 
 static void __init omapdss_add_to_list(struct device_node *node, bool root)
 {
-	struct dss_conv_node *n = kmalloc(sizeof(struct dss_conv_node),
-		GFP_KERNEL);
+	struct dss_conv_node *n = kmalloc(sizeof(*n), GFP_KERNEL);
 	if (n) {
 		n->node = node;
 		n->root = root;
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 2580e8673908..691cffebb76e 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -162,7 +162,7 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
 
 		dssdrv->get_timings(dssdev, &t);
 
-		if (memcmp(&vm, &t, sizeof(struct videomode)))
+		if (memcmp(&vm, &t, sizeof(vm)))
 			r = -EINVAL;
 		else
 			r = 0;
@@ -217,7 +217,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
 
 	omap_dss_get_device(dssdev);
 
-	omap_connector = kzalloc(sizeof(struct omap_connector), GFP_KERNEL);
+	omap_connector = kzalloc(sizeof(*omap_connector), GFP_KERNEL);
 	if (!omap_connector)
 		goto fail;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
index 4ceed7a9762f..3cab06661a08 100644
--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
+++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
@@ -224,7 +224,7 @@ static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
 	int rows = (1 + area->y1 - area->y0);
 	int i = columns*rows;
 
-	pat = alloc_dma(txn, sizeof(struct pat), &pat_pa);
+	pat = alloc_dma(txn, sizeof(*pat), &pat_pa);
 
 	if (txn->last_pat)
 		txn->last_pat->next_pa = (uint32_t)pat_pa;
@@ -735,7 +735,7 @@ static int omap_dmm_probe(struct platform_device *dev)
 
 	/* alloc engines */
 	omap_dmm->engines = kcalloc(omap_dmm->num_engines,
-				    sizeof(struct refill_engine), GFP_KERNEL);
+				    sizeof(*omap_dmm->engines), GFP_KERNEL);
 	if (!omap_dmm->engines) {
 		ret = -ENOMEM;
 		goto fail;
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index a20f30039aee..86c977b7189a 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -117,7 +117,7 @@ static int omap_encoder_update(struct drm_encoder *encoder,
 
 		dssdrv->get_timings(dssdev, &t);
 
-		if (memcmp(vm, &t, sizeof(struct videomode)))
+		if (memcmp(vm, &t, sizeof(*vm)))
 			ret = -EINVAL;
 		else
 			ret = 0;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 22/22] drm: omapdrm: Perform initialization/cleanup at probe/remove time
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (20 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 21/22] drm: omapdrm: Use sizeof(*var) instead of sizeof(type) for structures Laurent Pinchart
@ 2016-12-14  0:27 ` Laurent Pinchart
  2016-12-16 12:44   ` Tomi Valkeinen
  2016-12-19  9:15   ` [PATCH v4.1 " Laurent Pinchart
  2016-12-14  8:48 ` [PATCH v4 00/22] OMAP DRM fixes and improvements Tomi Valkeinen
  22 siblings, 2 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14  0:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The drm driver .load() operation is prone to race conditions as it
initializes the driver after registering the device nodes. Its usage is
deprecated, inline it in the probe function and call drm_dev_alloc() and
drm_dev_register() explicitly.

For consistency inline the .unload() handler in the remove function as
well.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Call drm_kms_helper_poll_fini() before omap_fbdev_free() in the remove
  handler.
- Keep storing drm_device in the platform device private data.
---
 drivers/gpu/drm/omapdrm/omap_connector.c |   2 -
 drivers/gpu/drm/omapdrm/omap_drv.c       | 212 ++++++++++++++++---------------
 2 files changed, 107 insertions(+), 107 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 691cffebb76e..f90e2d22c5ec 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -240,8 +240,6 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
 	connector->interlace_allowed = 1;
 	connector->doublescan_allowed = 0;
 
-	drm_connector_register(connector);
-
 	return connector;
 
 fail:
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 0a2d461d62cf..a3b37823b271 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -493,11 +493,6 @@ static int omap_modeset_init(struct drm_device *dev)
 	return 0;
 }
 
-static void omap_modeset_free(struct drm_device *dev)
-{
-	drm_mode_config_cleanup(dev);
-}
-
 /*
  * drm ioctl funcs
  */
@@ -633,95 +628,6 @@ static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] =
  * drm driver funcs
  */
 
-/**
- * load - setup chip and create an initial config
- * @dev: DRM device
- * @flags: startup flags
- *
- * The driver load routine has to do several things:
- *   - initialize the memory manager
- *   - allocate initial config memory
- *   - setup the DRM framebuffer with the allocated memory
- */
-static int dev_load(struct drm_device *dev, unsigned long flags)
-{
-	struct omap_drm_platform_data *pdata = dev->dev->platform_data;
-	struct omap_drm_private *priv;
-	unsigned int i;
-	int ret;
-
-	DBG("load: dev=%p", dev);
-
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->omaprev = pdata->omaprev;
-
-	dev->dev_private = priv;
-
-	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
-	init_waitqueue_head(&priv->commit.wait);
-	spin_lock_init(&priv->commit.lock);
-
-	spin_lock_init(&priv->list_lock);
-	INIT_LIST_HEAD(&priv->obj_list);
-
-	omap_gem_init(dev);
-
-	ret = omap_modeset_init(dev);
-	if (ret) {
-		dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
-		dev->dev_private = NULL;
-		kfree(priv);
-		return ret;
-	}
-
-	/* Initialize vblank handling, start with all CRTCs disabled. */
-	ret = drm_vblank_init(dev, priv->num_crtcs);
-	if (ret)
-		dev_warn(dev->dev, "could not init vblank\n");
-
-	for (i = 0; i < priv->num_crtcs; i++)
-		drm_crtc_vblank_off(priv->crtcs[i]);
-
-	priv->fbdev = omap_fbdev_init(dev);
-
-	/* store off drm_device for use in pm ops */
-	dev_set_drvdata(dev->dev, dev);
-
-	drm_kms_helper_poll_init(dev);
-
-	return 0;
-}
-
-static int dev_unload(struct drm_device *dev)
-{
-	struct omap_drm_private *priv = dev->dev_private;
-
-	DBG("unload: dev=%p", dev);
-
-	drm_kms_helper_poll_fini(dev);
-
-	if (priv->fbdev)
-		omap_fbdev_free(dev);
-
-	omap_modeset_free(dev);
-	omap_gem_deinit(dev);
-
-	destroy_workqueue(priv->wq);
-
-	drm_vblank_cleanup(dev);
-	omap_drm_irq_uninstall(dev);
-
-	kfree(dev->dev_private);
-	dev->dev_private = NULL;
-
-	dev_set_drvdata(dev->dev, NULL);
-
-	return 0;
-}
-
 static int dev_open(struct drm_device *dev, struct drm_file *file)
 {
 	file->driver_priv = NULL;
@@ -806,8 +712,6 @@ static const struct file_operations omapdriver_fops = {
 static struct drm_driver omap_drm_driver = {
 	.driver_features = DRIVER_MODESET | DRIVER_GEM  | DRIVER_PRIME |
 		DRIVER_ATOMIC,
-	.load = dev_load,
-	.unload = dev_unload,
 	.open = dev_open,
 	.lastclose = dev_lastclose,
 	.get_vblank_counter = drm_vblank_no_hw_counter,
@@ -837,30 +741,128 @@ static struct drm_driver omap_drm_driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
-static int pdev_probe(struct platform_device *device)
+static int pdev_probe(struct platform_device *pdev)
 {
-	int r;
+	struct omap_drm_platform_data *pdata = pdev->dev.platform_data;
+	struct omap_drm_private *priv;
+	struct drm_device *ddev;
+	unsigned int i;
+	int ret;
+
+	DBG("%s", pdev->name);
 
 	if (omapdss_is_initialized() == false)
 		return -EPROBE_DEFER;
 
 	omap_crtc_pre_init();
 
-	r = omap_connect_dssdevs();
-	if (r) {
+	ret = omap_connect_dssdevs();
+	if (ret) {
 		omap_crtc_pre_uninit();
-		return r;
+		goto err_crtc_uninit;
+	}
+
+	/* Allocate and initialize the driver private structure. */
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err_disconnect_dssdevs;
+	}
+
+	priv->omaprev = pdata->omaprev;
+	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
+
+	init_waitqueue_head(&priv->commit.wait);
+	spin_lock_init(&priv->commit.lock);
+	spin_lock_init(&priv->list_lock);
+	INIT_LIST_HEAD(&priv->obj_list);
+
+	/* Allocate and initialize the DRM device. */
+	ddev = drm_dev_alloc(&omap_drm_driver, &pdev->dev);
+	if (IS_ERR(ddev)) {
+		ret = PTR_ERR(ddev);
+		goto err_free_priv;
+	}
+
+	ddev->dev_private = priv;
+	platform_set_drvdata(pdev, ddev);
+
+	omap_gem_init(ddev);
+
+	ret = omap_modeset_init(ddev);
+	if (ret) {
+		dev_err(&pdev->dev, "omap_modeset_init failed: ret=%d\n", ret);
+		goto err_free_drm_dev;
+	}
+
+	/* Initialize vblank handling, start with all CRTCs disabled. */
+	ret = drm_vblank_init(ddev, priv->num_crtcs);
+	if (ret) {
+		dev_err(&pdev->dev, "could not init vblank\n");
+		goto err_cleanup_modeset;
 	}
 
-	DBG("%s", device->name);
-	return drm_platform_init(&omap_drm_driver, device);
+	for (i = 0; i < priv->num_crtcs; i++)
+		drm_crtc_vblank_off(priv->crtcs[i]);
+
+	priv->fbdev = omap_fbdev_init(ddev);
+
+	drm_kms_helper_poll_init(ddev);
+
+	/*
+	 * Register the DRM device with the core and the connectors with
+	 * sysfs.
+	 */
+	ret = drm_dev_register(ddev, 0);
+	if (ret)
+		goto err_cleanup_helpers;
+
+	return 0;
+
+err_cleanup_helpers:
+	drm_kms_helper_poll_fini(ddev);
+	if (priv->fbdev)
+		omap_fbdev_free(ddev);
+	drm_vblank_cleanup(ddev);
+err_cleanup_modeset:
+	drm_mode_config_cleanup(ddev);
+	omap_drm_irq_uninstall(ddev);
+err_free_drm_dev:
+	omap_gem_deinit(ddev);
+	drm_dev_unref(ddev);
+err_free_priv:
+	destroy_workqueue(priv->wq);
+	kfree(priv);
+err_disconnect_dssdevs:
+	omap_disconnect_dssdevs();
+err_crtc_uninit:
+	omap_crtc_pre_uninit();
+	return ret;
 }
 
-static int pdev_remove(struct platform_device *device)
+static int pdev_remove(struct platform_device *pdev)
 {
+	struct drm_device *ddev = platform_get_drvdata(pdev);
+	struct omap_drm_private *priv = ddev->dev_private;
+
 	DBG("");
 
-	drm_put_dev(platform_get_drvdata(device));
+	drm_dev_unregister(ddev);
+
+	drm_kms_helper_poll_fini(ddev);
+
+	if (priv->fbdev)
+		omap_fbdev_free(ddev);
+
+	drm_mode_config_cleanup(ddev);
+
+	omap_drm_irq_uninstall(ddev);
+	omap_gem_deinit(ddev);
+
+	drm_dev_unref(ddev);
+
+	destroy_workqueue(priv->wq);
+	kfree(priv);
 
 	omap_disconnect_dssdevs();
 	omap_crtc_pre_uninit();
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 00/22] OMAP DRM fixes and improvements
  2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (21 preceding siblings ...)
  2016-12-14  0:27 ` [PATCH v4 22/22] drm: omapdrm: Perform initialization/cleanup at probe/remove time Laurent Pinchart
@ 2016-12-14  8:48 ` Tomi Valkeinen
  2016-12-14 11:50   ` Laurent Pinchart
  22 siblings, 1 reply; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-14  8:48 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 21496 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> Hello,
> 
> Here's the fourth version of my current stack of pending patches for the
> omapdrm driver.
> 
> All comments received for v3 have been considered and patches updated where
> applicable. Patches 21/22 and 22/22 have been added, individual changelogs are
> available in all the patches when they have been modified.
> 
> The most notable change in this series is still the rework of the IRQ handling
> code (patches 06/22 to 19/22) that, beside simplifying the code, ensures that
> the vblank count and timestamp get updated properly in order to be reported to
> userspace.
> 
> The series is based on top of Dave's drm-next branch.

I got the following when unloading omapdrm modules, AM5 EVM with two displays:

[  758.762147] ------------[ cut here ]------------
[  758.767157] WARNING: CPU: 1 PID: 314 at drivers/gpu/drm/drm_irq.c:349 drm_vblank_cleanup+0x5c/0x94 [drm]
[  758.781401] Modules linked in: omapdrm(-) drm_kms_helper drm panel_dsi_cm panel_dpi connector_analog_tv connector_dvi connecto
r_hdmi encoder_tpd12s015 encoder_tfp410 omapdss cfbfillrect cfbimgblt cfbcopyarea [last unloaded: omapdss_base]
[  758.803761] CPU: 1 PID: 314 Comm: rmmod Not tainted 4.9.0-rc8-00106-g8df5349534c6 #53
[  758.811631] Hardware name: Generic DRA74X (Flattened Device Tree)
[  758.817755] Backtrace: 
[  758.820240] [<c010d8e0>] (dump_backtrace) from [<c010db8c>] (show_stack+0x18/0x1c)
[  758.827851]  r7:c0d830d8 r6:60030013 r5:00000000 r4:c0d830d8
[  758.833546] [<c010db74>] (show_stack) from [<c04d8668>] (dump_stack+0xa8/0xdc)
[  758.840813] [<c04d85c0>] (dump_stack) from [<c013c660>] (__warn+0xdc/0x108)
[  758.847814]  r9:bf1fefc0 r8:0000015d r7:00000009 r6:bf229b84 r5:00000000 r4:00000000
[  758.855602] [<c013c584>] (__warn) from [<c013c740>] (warn_slowpath_null+0x28/0x30)
[  758.863230]  r9:0000015d r8:bf229b84 r7:ee145000 r6:00000000 r5:00000000 r4:ed22aa00
.[  758.871173] [<c013c718>] (warn_slowpath_null) from [<bf1fefc0>] (drm_vblank_cleanup+0x5c/0x94 [drm])
[  758.880586] [<bf1fef64>] (drm_vblank_cleanup [drm]) from [<bf200760>] (drm_dev_unregister+0x58/0xbc [drm])
[  758.890291]  r9:ed3b4000 r8:c0ddb380 r7:00000000 r6:ee145000 r5:ee145000 r4:ee145000
[  758.898201] [<bf200708>] (drm_dev_unregister [drm]) from [<bf2ab26c>] (pdev_remove+0x2c/0x90 [omapdrm])
[  758.907643]  r7:00000000 r6:c0d0c25c r5:ed233000 r4:ee145000
[  758.913357] [<bf2ab240>] (pdev_remove [omapdrm]) from [<c05a1918>] (platform_drv_remove+0x2c/0x44)
[  758.922362]  r5:c0d0c228 r4:c0d0c228
[  758.925964] [<c05a18ec>] (platform_drv_remove) from [<c059ed24>] (__device_release_driver+0x90/0x12c)
[  758.935229]  r5:bf2b64e4 r4:c0d0c228
[  758.938829] [<c059ec94>] (__device_release_driver) from [<c059f9b0>] (driver_detach+0xc0/0xc4)
[  758.947484]  r5:bf2b64e4 r4:c0d0c228
[  758.951084] [<c059f8f0>] (driver_detach) from [<c059e764>] (bus_remove_driver+0x64/0xdc)
[  758.959217]  r7:c0b3bbfc r6:c0ddb368 r5:bf2b42e4 r4:bf2b64e4
[  758.964911] [<c059e700>] (bus_remove_driver) from [<c05a079c>] (driver_unregister+0x30/0x50)
[  758.973390]  r5:bf2b42e4 r4:bf2b64e4
[  758.976991] [<c05a076c>] (driver_unregister) from [<c05a1a3c>] (platform_unregister_drivers+0x3c/0x74)
[  758.986343]  r5:bf2b42e4 r4:00000000
[  758.989961] [<c05a1a00>] (platform_unregister_drivers) from [<bf2b42b8>] (omap_drm_fini+0x28/0x38 [omapdrm])
[  758.999841]  r9:ed3b4000 r8:c0108c04 r7:00000081 r6:00000800 r5:0003cd4c r4:bf2b6800
[  759.007649] [<bf2b4290>] (omap_drm_fini [omapdrm]) from [<c01e63d4>] (SyS_delete_module+0x144/0x21c)
[  759.016835] [<c01e6290>] (SyS_delete_module) from [<c0108a60>] (ret_fast_syscall+0x0/0x1c)
[  759.025142]  r6:bec63c10 r5:0003cd10 r4:bec63dfc
[  759.029902] ---[ end trace ebaa3f100ebbc054 ]---
[  759.036433] ------------[ cut here ]------------
[  759.041394] WARNING: CPU: 1 PID: 314 at drivers/gpu/drm/drm_irq.c:349 drm_vblank_cleanup+0x5c/0x94 [drm]
[  759.050963] Modules linked in: omapdrm(-) drm_kms_helper drm panel_dsi_cm panel_dpi connector_analog_tv connector_dvi connecto
r_hdmi encoder_tpd12s015 encoder_tfp410 omapdss cfbfillrect cfbimgblt cfbcopyarea [last unloaded: omapdss_base]
[  759.072372] CPU: 1 PID: 314 Comm: rmmod Tainted: G        W       4.9.0-rc8-00106-g8df5349534c6 #53
[  759.081462] Hardware name: Generic DRA74X (Flattened Device Tree)
[  759.087584] Backtrace: 
[  759.090064] [<c010d8e0>] (dump_backtrace) from [<c010db8c>] (show_stack+0x18/0x1c)
[  759.097675]  r7:c0d830d8 r6:60030013 r5:00000000 r4:c0d830d8
[  759.103368] [<c010db74>] (show_stack) from [<c04d8668>] (dump_stack+0xa8/0xdc)
[  759.110633] [<c04d85c0>] (dump_stack) from [<c013c660>] (__warn+0xdc/0x108)
[  759.117634]  r9:bf1fefc0 r8:0000015d r7:00000009 r6:bf229b84 r5:00000000 r4:00000000
[  759.125421] [<c013c584>] (__warn) from [<c013c740>] (warn_slowpath_null+0x28/0x30)
[  759.133033]  r9:0000015d r8:bf229b84 r7:ee145000 r6:00000001 r5:000000c8 r4:ed22aac8
/[  759.140927] [<c013c718>] (warn_slowpath_null) from [<bf1fefc0>] (drm_vblank_cleanup+0x5c/0x94 [drm])
[  759.150391] [<bf1fef64>] (drm_vblank_cleanup [drm]) from [<bf200760>] (drm_dev_unregister+0x58/0xbc [drm])
[  759.160097]  r9:ed3b4000 r8:c0ddb380 r7:00000000 r6:ee145000 r5:ee145000 r4:ee145000
[  759.168006] [<bf200708>] (drm_dev_unregister [drm]) from [<bf2ab26c>] (pdev_remove+0x2c/0x90 [omapdrm])
[  759.177448]  r7:00000000 r6:c0d0c25c r5:ed233000 r4:ee145000
[  759.183161] [<bf2ab240>] (pdev_remove [omapdrm]) from [<c05a1918>] (platform_drv_remove+0x2c/0x44)
[  759.192164]  r5:c0d0c228 r4:c0d0c228
[  759.195766] [<c05a18ec>] (platform_drv_remove) from [<c059ed24>] (__device_release_driver+0x90/0x12c)
[  759.205031]  r5:bf2b64e4 r4:c0d0c228
[  759.208632] [<c059ec94>] (__device_release_driver) from [<c059f9b0>] (driver_detach+0xc0/0xc4)
[  759.217287]  r5:bf2b64e4 r4:c0d0c228
[  759.220887] [<c059f8f0>] (driver_detach) from [<c059e764>] (bus_remove_driver+0x64/0xdc)
[  759.229021]  r7:c0b3bbfc r6:c0ddb368 r5:bf2b42e4 r4:bf2b64e4
[  759.234715] [<c059e700>] (bus_remove_driver) from [<c05a079c>] (driver_unregister+0x30/0x50)
[  759.243196]  r5:bf2b42e4 r4:bf2b64e4
[  759.246797] [<c05a076c>] (driver_unregister) from [<c05a1a3c>] (platform_unregister_drivers+0x3c/0x74)
[  759.256151]  r5:bf2b42e4 r4:00000000
[  759.259770] [<c05a1a00>] (platform_unregister_drivers) from [<bf2b42b8>] (omap_drm_fini+0x28/0x38 [omapdrm])
[  759.269650]  r9:ed3b4000 r8:c0108c04 r7:00000081 r6:00000800 r5:0003cd4c r4:bf2b6800
[  759.277456] [<bf2b4290>] (omap_drm_fini [omapdrm]) from [<c01e63d4>] (SyS_delete_module+0x144/0x21c)
[  759.286641] [<c01e6290>] (SyS_delete_module) from [<c0108a60>] (ret_fast_syscall+0x0/0x1c)
[  759.294948]  r6:bec63c10 r5:0003cd10 r4:bec63dfc
[  759.299701] ---[ end trace ebaa3f100ebbc055 ]---
[  759.309098] ------------[ cut here ]------------
[  759.313879] WARNING: CPU: 0 PID: 7 at drivers/gpu/drm/drm_irq.c:1708 drm_handle_vblank+0x398/0x3c8 [drm]
[  759.323401] Modules linked in: omapdrm(-) drm_kms_helper drm panel_dsi_cm panel_dpi connector_analog_tv connector_dvi connecto
r_hdmi encoder_tpd12s015 encoder_tfp410 omapdss cfbfillrect cfbimgblt cfbcopyarea [last unloaded: omapdss_base]
[  759.344721] CPU: 0 PID: 7 Comm: rcu_preempt Tainted: G        W       4.9.0-rc8-00106-g8df5349534c6 #53
[  759.354155] Hardware name: Generic DRA74X (Flattened Device Tree)
[  759.360276] Backtrace: 
[  759.362752] [<c010d8e0>] (dump_backtrace) from [<c010db8c>] (show_stack+0x18/0x1c)
[  759.370359]  r7:c0d830d8 r6:600f0193 r5:00000000 r4:c0d830d8
[  759.376049] [<c010db74>] (show_stack) from [<c04d8668>] (dump_stack+0xa8/0xdc)
[  759.383312] [<c04d85c0>] (dump_stack) from [<c013c660>] (__warn+0xdc/0x108)
[  759.390310]  r9:bf1fede4 r8:000006ac r7:00000009 r6:bf229b84 r5:00000000 r4:00000000
[  759.398094] [<c013c584>] (__warn) from [<c013c740>] (warn_slowpath_null+0x28/0x30)
[  759.405701]  r9:ee145000 r8:ee145000 r7:00000001 r6:ed233000 r5:00000802 r4:ed22aac8
[  759.413589] [<c013c718>] (warn_slowpath_null) from [<bf1fede4>] (drm_handle_vblank+0x398/0x3c8 [drm])
[  759.422980] [<bf1fea4c>] (drm_handle_vblank [drm]) from [<bf2ac188>] (omap_irq_handler+0x88/0x210 [omapdrm])
[  759.432856]  r10:00000000 r9:ee145000 r8:ed23300c r7:ed0ae800 r6:ed233000 r5:00000802
[  759.440719]  r4:00000001
[  759.443370] [<bf2ac100>] (omap_irq_handler [omapdrm]) from [<bf1757a8>] (dispc_irq_handler+0x34/0x3c [omapdss])
[  759.453507]  r10:c0d0512c r9:0000015e r8:c0d05db0 r7:ee0ea000 r6:c0d836b0 r5:ee0ea000
[  759.461372]  r4:ed19db80
[  759.464002] [<bf175774>] (dispc_irq_handler [omapdss]) from [<c01afd74>] (__handle_irq_event_percpu+0x54/0x488)
[  759.474142] [<c01afd20>] (__handle_irq_event_percpu) from [<c01b01cc>] (handle_irq_event_percpu+0x24/0x60)
[  759.483841]  r10:0000015e r9:00000001 r8:c0d05db0 r7:ee0ea000 r6:c0d836b0 r5:ee336200
[  759.491706]  r4:ee336200
[  759.494256] [<c01b01a8>] (handle_irq_event_percpu) from [<c01b0248>] (handle_irq_event+0x40/0x64)
[  759.503169]  r5:ee336260 r4:ee336200
[  759.506768] [<c01b0208>] (handle_irq_event) from [<c01b3b30>] (handle_fasteoi_irq+0xec/0x1cc)
[  759.515332]  r7:ee0ea000 r6:c0d836b0 r5:ee336260 r4:ee336200
[  759.521021] [<c01b3a44>] (handle_fasteoi_irq) from [<c01aeeec>] (generic_handle_irq+0x28/0x3c)
[  759.529674]  r9:00000001 r8:00000000 r7:c0d05db0 r6:ee0ea000 r5:c0c7c274 r4:c0c7c274
[  759.537458] [<c01aeec4>] (generic_handle_irq) from [<c01af4f8>] (__handle_domain_irq+0x98/0x134)
[  759.546288] [<c01af460>] (__handle_domain_irq) from [<c01015d4>] (gic_handle_irq+0x58/0xbc)
[  759.554679]  r10:c0d05fe4 r9:fa212000 r8:c0d836a0 r7:ee0ebd38 r6:000003ff r5:000003eb
[  759.562544]  r4:fa21200c
[  759.565096] [<c010157c>] (gic_handle_irq) from [<c08d6e30>] (__irq_svc+0x70/0xb0)
[  759.572612] Exception stack(0xee0ebd38 to 0xee0ebd80)
[  759.577688] bd20:                                                       00000001 00000001
[  759.585907] bd40: 00000000 ee0e8e80 eed8b080 00000000 c0d08980 00000000 00000001 ee0e8e80
[  759.594123] bd60: c08cfa70 ee0ebd9c ee0ebd58 ee0ebd88 c019f9a0 c08d6458 200f0013 ffffffff
[  759.602341]  r10:c08cfa70 r9:ee0ea000 r8:00000001 r7:ee0ebd6c r6:ffffffff r5:200f0013
[  759.610204]  r4:c08d6458
[  759.612756] [<c08d6428>] (_raw_spin_unlock_irq) from [<c016c6d4>] (finish_task_switch+0xdc/0x284)
[  759.621669]  r5:00000000 r4:eed8b080
[  759.625266] [<c016c5f8>] (finish_task_switch) from [<c08cfa70>] (__schedule+0x3fc/0xd3c)
[  759.633396]  r10:ee0e9180 r9:00000000 r8:ed084240 r7:00002f1f r6:c0d08980 r5:ee0e8e80
[  759.641261]  r4:eed8b090
[  759.643810] [<c08cf674>] (__schedule) from [<c08d0408>] (schedule+0x58/0xb8)
[  759.650894]  r10:00000000 r9:000008b9 r8:eed865c0 r7:c0d04900 r6:00000000 r5:00000001
[  759.658759]  r4:ee0ea000
[  759.661308] [<c08d03b0>] (schedule) from [<c08d542c>] (schedule_timeout+0x208/0x4fc)
[  759.669088]  r7:c0d04900 r6:eed865c0 r5:ee0ebe88 r4:0000b35a
[  759.674778] [<c08d5224>] (schedule_timeout) from [<c01bf228>] (rcu_gp_kthread+0x5a4/0x974)
[  759.683086]  r10:00000001 r9:000008b9 r8:00000000 r7:c0d45210 r6:c0d45238 r5:00000001
[  759.690953]  r4:c0d44f80
[  759.693502] [<c01bec84>] (rcu_gp_kthread) from [<c0163890>] (kthread+0xe4/0x108)
[  759.700931]  r7:c01bec84
[  759.703482] [<c01637ac>] (kthread) from [<c0108af0>] (ret_from_fork+0x14/0x24)
[  759.710738]  r7:00000000 r6:00000000 r5:c01637ac r4:ee088900
[  759.716423] ---[ end trace ebaa3f100ebbc056 ]---
^H[  759.789292] ------------[ cut here ]------------
[  759.794068] WARNING: CPU: 1 PID: 314 at drivers/gpu/drm/drm_irq.c:1278 drm_crtc_vblank_off+0x1b0/0x1cc [drm]
[  759.804252] Modules linked in: omapdrm(-) drm_kms_helper drm panel_dsi_cm panel_dpi connector_analog_tv connector_dvi connecto
r_hdmi encoder_tpd12s015 encoder_tfp410 omapdss cfbfillrect cfbimgblt cfbcopyarea [last unloaded: omapdss_base]
[  759.826582] CPU: 1 PID: 314 Comm: rmmod Tainted: G        W       4.9.0-rc8-00106-g8df5349534c6 #53
[  759.835673] Hardware name: Generic DRA74X (Flattened Device Tree)
[  759.841797] Backtrace: 
[  759.844276] [<c010d8e0>] (dump_backtrace) from [<c010db8c>] (show_stack+0x18/0x1c)
[  759.851888]  r7:c0d830d8 r6:600e0013 r5:00000000 r4:c0d830d8
[  759.857581] [<c010db74>] (show_stack) from [<c04d8668>] (dump_stack+0xa8/0xdc)
[  759.864845] [<c04d85c0>] (dump_stack) from [<c013c660>] (__warn+0xdc/0x108)
[  759.871846]  r9:bf1fea30 r8:000004fe r7:00000009 r6:bf229b84 r5:00000000 r4:00000000
[  759.879632] [<c013c584>] (__warn) from [<c013c740>] (warn_slowpath_null+0x28/0x30)
[  759.887244]  r9:ee145000 r8:bf2b4ad0 r7:00000000 r6:ed23f200 r5:00000000 r4:ed22aa00
[  759.895139] [<c013c718>] (warn_slowpath_null) from [<bf1fea30>] (drm_crtc_vblank_off+0x1b0/0x1cc [drm])
[  759.904707] [<bf1fe880>] (drm_crtc_vblank_off [drm]) from [<bf2ace38>] (omap_crtc_disable+0x2c/0x38 [omapdrm])
[  759.914761]  r10:bf286140 r9:bf286110 r8:bf2b4ad0 r7:ed0c8000 r6:ed23f200 r5:00000000
[  759.922628]  r4:ed0c8000
[  759.925256] [<bf2ace0c>] (omap_crtc_disable [omapdrm]) from [<bf27aaec>] (drm_atomic_helper_commit_modeset_disables+0x1c0/0x41
4 [drm_kms_helper])
[  759.938360]  r5:00000000 r4:ed19db00
[  759.942026] [<bf27a92c>] (drm_atomic_helper_commit_modeset_disables [drm_kms_helper]) from [<bf2ab528>] (omap_atomic_complete+
0x2c/0x15c [omapdrm])
[  759.955305]  r10:bf22c188 r9:00000000 r8:ed233000 r7:ed19d780 r6:ee145000 r5:ed19db00
[  759.963173]  r4:ed233128
[  759.965759] [<bf2ab4fc>] (omap_atomic_complete [omapdrm]) from [<bf2ab7d8>] (omap_atomic_commit+0x180/0x268 [omapdrm])
[  759.976508]  r9:00000000 r8:00000000 r7:ed233000 r6:ed19db00 r5:ed19d780 r4:ed233128
[  759.984420] [<bf2ab658>] (omap_atomic_commit [omapdrm]) from [<bf210d54>] (drm_atomic_commit+0x54/0x60 [drm])
[  759.994386]  r10:bf22c188 r9:bf22c1b8 r8:ee145000 r7:ed3b5e04 r6:ee145000 r5:ed19db00
[  760.002254]  r4:00000000
[  760.004960] [<bf210d00>] (drm_atomic_commit [drm]) from [<bf27dffc>] (drm_atomic_helper_set_config+0x80/0xd8 [drm_kms_helper])
[  760.016406]  r7:ed3b5e04 r6:ed0c8000 r5:00000000 r4:ed19db00
[  760.022250] [<bf27df7c>] (drm_atomic_helper_set_config [drm_kms_helper]) from [<bf2046b8>] (drm_mode_set_config_internal+0x6c/
0xfc [drm])
[  760.034656]  r7:ee14548c r6:ee145480 r5:ed0c8000 r4:00000000
[  760.040558] [<bf20464c>] (drm_mode_set_config_internal [drm]) from [<bf204780>] (drm_crtc_force_disable+0x38/0x40 [drm])
[  760.051481]  r7:ee14548c r6:ee145480 r5:ed24f800 r4:ed0c8000
[  760.057384] [<bf204748>] (drm_crtc_force_disable [drm]) from [<bf212e94>] (drm_framebuffer_remove+0xd0/0x110 [drm])
[  760.067997] [<bf212dc4>] (drm_framebuffer_remove [drm]) from [<bf2b4274>] (omap_fbdev_free+0x60/0x7c [omapdrm])
[  760.078138]  r10:00000000 r9:ed3b4000 r8:c0ddb380 r7:00000000 r6:c0d0c25c r5:ed233000
[  760.086007]  r4:ed285200 r3:00000001
[  760.089639] [<bf2b4214>] (omap_fbdev_free [omapdrm]) from [<bf2ab288>] (pdev_remove+0x48/0x90 [omapdrm])
[  760.099165]  r5:ed233000 r4:ee145000
[  760.102784] [<bf2ab240>] (pdev_remove [omapdrm]) from [<c05a1918>] (platform_drv_remove+0x2c/0x44)
[  760.111788]  r5:c0d0c228 r4:c0d0c228
[  760.115390] [<c05a18ec>] (platform_drv_remove) from [<c059ed24>] (__device_release_driver+0x90/0x12c)
[  760.124653]  r5:bf2b64e4 r4:c0d0c228
[  760.128252] [<c059ec94>] (__device_release_driver) from [<c059f9b0>] (driver_detach+0xc0/0xc4)
[  760.136907]  r5:bf2b64e4 r4:c0d0c228
[  760.140507] [<c059f8f0>] (driver_detach) from [<c059e764>] (bus_remove_driver+0x64/0xdc)
[  760.148638]  r7:c0b3bbfc r6:c0ddb368 r5:bf2b42e4 r4:bf2b64e4
[  760.154331] [<c059e700>] (bus_remove_driver) from [<c05a079c>] (driver_unregister+0x30/0x50)
[  760.162810]  r5:bf2b42e4 r4:bf2b64e4
[  760.166411] [<c05a076c>] (driver_unregister) from [<c05a1a3c>] (platform_unregister_drivers+0x3c/0x74)
[  760.175771]  r5:bf2b42e4 r4:00000000
[  760.179389] [<c05a1a00>] (platform_unregister_drivers) from [<bf2b42b8>] (omap_drm_fini+0x28/0x38 [omapdrm])
[  760.189267]  r9:ed3b4000 r8:c0108c04 r7:00000081 r6:00000800 r5:0003cd4c r4:bf2b6800
[  760.197073] [<bf2b4290>] (omap_drm_fini [omapdrm]) from [<c01e63d4>] (SyS_delete_module+0x144/0x21c)
[  760.206256] [<c01e6290>] (SyS_delete_module) from [<c0108a60>] (ret_fast_syscall+0x0/0x1c)
[  760.214562]  r6:bec63c10 r5:0003cd10 r4:bec63dfc
^H^H[  760.219458] ---[ end trace ebaa3f100ebbc057 ]---
[  760.233226] ------------[ cut here ]------------
^H[  760.237992] WARNING: CPU: 1 PID: 314 at drivers/gpu/drm/drm_irq.c:1278 drm_crtc_vblank_off+0x1b0/0x1cc [drm]
[  760.248043] Modules linked in: omapdrm(-) drm_kms_helper drm panel_dsi_cm panel_dpi connector_analog_tv connector_dvi connecto
r_hdmi encoder_tpd12s015 encoder_tfp410 omapdss cfbfillrect^H cfbimgblt cfbcopyarea [last unloaded: omapdss_base]
[  760.269659] CPU: 1 PID: 314 Comm: rmmod Tainted: G        W       4.9.0-rc8-00106-g8df5349534c6 #53
[  760.278750] Hardware name: Generic DRA74X (Flattened Device Tree)
[  760.284873] Backtrace: 
[  760.287353] [<c010d8e0>] (dump_backtrace) from [<c010db8c>] (show_stack+0x18/0x1c)
[  760.294965]  r7:c0d830d8 r6:600e0013 r5:00000000 r4:c0d830d8
[  760.300660] [<c010db74>] (show_stack) from [<c04d8668>] (dump_stack+0xa8/0xdc)
^H[  760.307943] [<c04d85c0>] (dump_stack) from [<c013c660>] (__warn+0xdc/0x108)
[  760.315115]  r9:bf1fea30 r8:000004fe r7:00000009 r6:bf229b84 r5:00000000 r4:00000000
[  760.322906] [<c013c584>] (__warn) from [<c013c740>] (warn_slowpath_null+0x28/0x30)
[  760.330533]  r9:ee145000 r8:bf2b4ad0 r7:00000001 r6:ed23f800 r5:00000001 r4:ed22aac8
^H[  760.338427] [<c013c718>] (warn_slowpath_null) from [<bf1fea30>] (drm_crtc_vblank_off+0x1b0/0x1cc [drm])
[  760.348059] [<bf1fe880>] (drm_crtc_vblank_off [drm]) from [<bf2ace38>] (omap_crtc_disable+0x2c/0x38 [omapdrm])
[  760.358112]  r10:bf286140 r9:bf286110 r8:bf2b4ad0 r7:ed0ae800 r6:ed23f800 r5:00000001
[  760.365981]  r4:ed0ae800
[  760.368604] [<bf2ace0c>] (omap_crtc_disable [omapdrm]) from [<bf27aaec>] (drm_atomic_helper_commit_modeset_disables+0x1c0/0x41
4 [drm_kms_helper])
[  760.381709]  r5:00000001 r4:ed19db00
^H[  760.385374] [<bf27a92c>] (drm_atomic_helper_commit_modeset_disables [drm_kms_helper]) from [<bf2ab528>] (omap_atomic_complet
e+0x2c/0x15c [omapdrm])
[  760.398782]  r10:bf22c188 r9:00000000 r8:ed233000 r7:ed19d780 r6:ee145000 r5:ed19db00
[  760.406650]  r4:ed233128
^H[  760.409235] [<bf2ab4fc>] (omap_atomic_complete [omapdrm]) from [<bf2ab7d8>] (omap_atomic_commit+0x180/0x268 [omapdrm])
[  760.420164]  r9:00000000 r8:00000000 r7:ed233000 r6:ed19db00 r5:ed19d780 r4:ed233128
^H[  760.428075] [<bf2ab658>] (omap_atomic_commit [omapdrm]) from [<bf210d54>] (drm_atomic_commit+0x54/0x60 [drm])
[  760.438105]  r10:bf22c188 r9:bf22c1b8 r8:ee145000 r7:ed3b5e04 r6:ee145000 r5:ed19db00
[  760.445974]  r4:00000000
^H[  760.448691] [<bf210d00>] (drm_atomic_commit [drm]) from [<bf27dffc>] (drm_atomic_helper_set_config+0x80/0xd8 [drm_kms_helper
])
[  760.460160]  r7:ed3b5e04 r6:ed0ae800 r5:00000000 r4:ed19db00
[  760.466007] [<bf27df7c>] (drm_atomic_helper_set_config [drm_kms_helper]) from [<bf2046b8>] (drm_mode_set_config_internal+0x6c/
0xfc [drm])
[  760.478413]  r7:ee14548c r6:ee145480 r5:ed0ae800 r4:00000000
^H[  760.484317] [<bf20464c>] (drm_mode_set_config_internal [drm]) from [<bf204780>] (drm_crtc_force_disable+0x38/0x40 [drm])
[  760.495293]  r7:ee14548c r6:ee145480 r5:ed24f800 r4:ed0ae800
[  760.501196] [<bf204748>] (drm_crtc_force_disable [drm]) from [<bf212e94>] (drm_framebuffer_remove+0xd0/0x110 [drm])
^H[  760.511807] [<bf212dc4>] (drm_framebuffer_remove [drm]) from [<bf2b4274>] (omap_fbdev_free+0x60/0x7c [omapdrm])
[  760.522090]  r10:00000000 r9:ed3b4000 r8:c0ddb380 r7:00000000 r6:c0d0c25c r5:ed233000
[  760.529959]  r4:ed285200 r3:00000001
[  760.533591] [<bf2b4214>] (omap_fbdev_free [omapdrm]) from [<bf2ab288>] (pdev_remove+0x48/0x90 [omapdrm])
[  760.543118]  r5:ed233000 r4:ee145000
^H[  760.546738] [<bf2ab240>] (pdev_remove [omapdrm]) from [<c05a1918>] (platform_drv_remove+0x2c/0x44)
[  760.555893]  r5:c0d0c228 r4:c0d0c228
[  760.559495] [<c05a18ec>] (platform_drv_remove) from [<c059ed24>] (__device_release_driver+0x90/0x12c)
[  760.568760]  r5:bf2b64e4 r4:c0d0c228
[  760.572379] [<c059ec94>] (__device_release_driver) from [<c059f9b0>] (driver_detach+0xc0/0xc4)
[  760.581033]  r5:bf2b64e4 r4:c0d0c228
^H[  760.584633] [<c059f8f0>] (driver_detach) from [<c059e764>] (bus_remove_driver+0x64/0xdc)
[  760.592936]  r7:c0b3bbfc r6:c0ddb368 r5:bf2b42e4 r4:bf2b64e4
[  760.598627] [<c059e700>] (bus_remove_driver) from [<c05a079c>] (driver_unregister+0x30/0x50)
[  760.607106]  r5:bf2b42e4 r4:bf2b64e4
[  760.610707] [<c05a076c>] (driver_unregister) from [<c05a1a3c>] (platform_unregister_drivers+0x3c/0x74)
[  760.620078]  r5:bf2b42e4 r4:00000000
^H[  760.623697] [<c05a1a00>] (platform_unregister_drivers) from [<bf2b42b8>] (omap_drm_fini+0x28/0x38 [omapdrm])
[  760.633730]  r9:ed3b4000 r8:c0108c04 r7:00000081 r6:00000800 r5:0003cd4c r4:bf2b6800
[  760.641536] [<bf2b4290>] (omap_drm_fini [omapdrm]) from [<c01e63d4>] (SyS_delete_module+0x144/0x21c)
[  760.650725] [<c01e6290>] (SyS_delete_module) from [<c0108a60>] (ret_fast_syscall+0x0/0x1c)
[  760.659033]  r6:bec63c10 r5:0003cd10 r4:bec63dfc
^H[  760.663832] ---[ end trace ebaa3f100ebbc058 ]---


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 02/22] drm: omapdrm: fb: Use format information provided by the DRM core
  2016-12-14  0:27 ` [PATCH v4 02/22] drm: omapdrm: fb: Use format information provided by the DRM core Laurent Pinchart
@ 2016-12-14 10:07   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-14 10:07 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 641 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> The driver stores in a custom structure named format several pieces of
> information about the format that are available in the DRM core. Remove
> them and get the information from the DRM core instead.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v3:
> 
> - Fix subsampling computation by checking the plane number correctly
> ---
>  drivers/gpu/drm/omapdrm/omap_fb.c | 91 ++++++++++++++++++++-------------------
>  1 file changed, 46 insertions(+), 45 deletions(-)

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 06/22] drm: omapdrm: Handle FIFO underflow IRQs internally
  2016-12-14  0:27 ` [PATCH v4 06/22] drm: omapdrm: Handle FIFO underflow IRQs internally Laurent Pinchart
@ 2016-12-14 10:22   ` Tomi Valkeinen
  2016-12-14 11:48     ` Laurent Pinchart
  0 siblings, 1 reply; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-14 10:22 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 1591 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> As the FIFO underflow IRQ handler just prints an error message to the
> kernel log, simplify the code by not registering one IRQ handler per
> plane but print the messages directly from the main IRQ handler.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---

> +static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
> +				    u32 irqstatus)
> +{
> +	static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
> +				      DEFAULT_RATELIMIT_BURST);
> +	static const struct {
> +		const char *name;
> +		u32 mask;
> +	} sources[] = {
> +		{ "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW },
> +		{ "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW },
> +		{ "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW },
> +		{ "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW },
> +	};
> +
> +	const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW
> +		       | DISPC_IRQ_VID1_FIFO_UNDERFLOW
> +		       | DISPC_IRQ_VID2_FIFO_UNDERFLOW
> +		       | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
> +	unsigned int i;
> +
> +	spin_lock(&list_lock);
> +	irqstatus &= priv->irq_mask & mask;
> +	spin_unlock(&list_lock);
> +
> +	if (!irqstatus)
> +		return;

This is called every time we get any DSS interrupt, so I think it would
be good to have a fast-path here without the lock: irqstatus & mask.

Or maybe store the enabled underflow irq bits separately from irq_mask,
as the underflow bits are never changed after the initial setup, and
then there's no need for locking.

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 08/22] drm: omapdrm: Handle OCP error IRQ directly
  2016-12-14  0:27 ` [PATCH v4 08/22] drm: omapdrm: Handle OCP error IRQ directly Laurent Pinchart
@ 2016-12-14 10:24   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-14 10:24 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 3573 bytes --]


On 14/12/16 02:27, Laurent Pinchart wrote:
> Instead of going through a complicated registration mechanism, just
> call the OCP error IRQ handler directly from the main IRQ handler.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v1:
> 
> - Rename IRQ handler to omap_irq_ocp_error_handler()
> - Replace hex error value with "OCP error" message
> ---
>  drivers/gpu/drm/omapdrm/omap_drv.h |  1 -
>  drivers/gpu/drm/omapdrm/omap_irq.c | 28 ++++++++++------------------
>  2 files changed, 10 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
> index 0d88c9798df9..851629e8704e 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.h
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.h
> @@ -103,7 +103,6 @@ struct omap_drm_private {
>  	/* irq handling: */
>  	struct list_head irq_list;    /* list of omap_drm_irq */
>  	uint32_t irq_mask;		/* enabled irqs in addition to irq_list */
> -	struct omap_drm_irq error_handler;
>  
>  	/* atomic commit */
>  	struct {
> diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
> index 58c5efb26766..e1925fa6d849 100644
> --- a/drivers/gpu/drm/omapdrm/omap_irq.c
> +++ b/drivers/gpu/drm/omapdrm/omap_irq.c
> @@ -21,12 +21,6 @@
>  
>  static DEFINE_SPINLOCK(list_lock);
>  
> -static void omap_irq_error_handler(struct omap_drm_irq *irq,
> -		uint32_t irqstatus)
> -{
> -	DRM_ERROR("errors: %08x\n", irqstatus);
> -}
> -
>  /* call with list_lock and dispc runtime held */
>  static void omap_irq_update(struct drm_device *dev)
>  {
> @@ -224,6 +218,14 @@ static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
>  	pr_cont("(0x%08x)\n", irqstatus);
>  }
>  
> +static void omap_irq_ocp_error_handler(u32 irqstatus)
> +{
> +	if (!(irqstatus & DISPC_IRQ_OCP_ERR))
> +		return;
> +
> +	DRM_ERROR("OCP error\n");
> +}
> +
>  static irqreturn_t omap_irq_handler(int irq, void *arg)
>  {
>  	struct drm_device *dev = (struct drm_device *) arg;
> @@ -250,6 +252,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
>  			omap_crtc_error_irq(crtc, irqstatus);
>  	}
>  
> +	omap_irq_ocp_error_handler(irqstatus);
>  	omap_irq_fifo_underflow(priv, irqstatus);
>  
>  	spin_lock_irqsave(&list_lock, flags);
> @@ -282,7 +285,6 @@ static const u32 omap_underflow_irqs[] = {
>  int omap_drm_irq_install(struct drm_device *dev)
>  {
>  	struct omap_drm_private *priv = dev->dev_private;
> -	struct omap_drm_irq *error_handler = &priv->error_handler;
>  	unsigned int num_mgrs = dss_feat_get_num_mgrs();
>  	unsigned int max_planes;
>  	unsigned int i;
> @@ -290,7 +292,7 @@ int omap_drm_irq_install(struct drm_device *dev)
>  
>  	INIT_LIST_HEAD(&priv->irq_list);
>  
> -	priv->irq_mask = 0;
> +	priv->irq_mask = DISPC_IRQ_OCP_ERR;
>  
>  	max_planes = min(ARRAY_SIZE(priv->planes),
>  			 ARRAY_SIZE(omap_underflow_irqs));
> @@ -310,16 +312,6 @@ int omap_drm_irq_install(struct drm_device *dev)
>  	if (ret < 0)
>  		return ret;
>  
> -	error_handler->irq = omap_irq_error_handler;
> -	error_handler->irqmask = DISPC_IRQ_OCP_ERR;
> -
> -	/* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think
> -	 * we just need to ignore it while enabling tv-out
> -	 */
> -	error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
> -
> -	omap_irq_register(dev, error_handler);
> -
>  	dev->irq_enabled = true;
>  
>  	return 0;
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 18/22] drm: omapdrm: Inline the pipe2vbl function
  2016-12-14  0:27 ` [PATCH v4 18/22] drm: omapdrm: Inline the pipe2vbl function Laurent Pinchart
@ 2016-12-14 10:25   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-14 10:25 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 423 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> The function is only used in omap_irq.c and is just a wrapper around
> dispc_mgr_get_vsync_irq(). Remove it and call the dispc function
> directly.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v3:
> 
> - Removed the pipe2vbl function completely
> ---

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 09/22] drm: omapdrm: Replace DSS manager state check with omapdrm CRTC state
  2016-12-14  0:27 ` [PATCH v4 09/22] drm: omapdrm: Replace DSS manager state check with omapdrm CRTC state Laurent Pinchart
@ 2016-12-14 10:36   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-14 10:36 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 1179 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> Instead of conditioning planes update based on the DSS manager hardware
> state, use the enabled field newly added to the omap_crtc structure.
> This reduces the dependency from the DRM layer to the DSS layer.
> 
> The enabled field is a transitory measure, the implementation should use
> the CRTC atomic state instead. However, given that CRTCs are currently
> not enabled/disabled through their .enable() and .disable() operations
> but through a convoluted code paths starting at the associated encoder
> operations, there is not clear guarantee that the atomic state always
> matches the hardware state. This will be refactored later, at which
> point the enabled field will be removed.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v3:
> 
> - Clarify commit message
> 
> Changes since v2:
> 
> - Use enabled field in struct omap_crtc instead of CRTC atomic state
> ---
>  drivers/gpu/drm/omapdrm/omap_crtc.c | 22 +++++++++++++---------
>  1 file changed, 13 insertions(+), 9 deletions(-)

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 10/22] drm: omapdrm: Let the DRM core skip plane commit on inactive CRTCs
  2016-12-14  0:27 ` [PATCH v4 10/22] drm: omapdrm: Let the DRM core skip plane commit on inactive CRTCs Laurent Pinchart
@ 2016-12-14 10:43   ` Tomi Valkeinen
  2016-12-14 11:26     ` Laurent Pinchart
  0 siblings, 1 reply; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-14 10:43 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 2661 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> The DRM core supports skipping plane update for inactive CRTCs for
> hardware that don't need it or can't cope with it. That's our case, and
> the driver already skips flushing planes on inactice CRTCs.
> 
> We can't remove the check from the driver, as active CRTCs are disabled
> at the hardware level when an atomic flush is performed if a mode set is
> pending. There's however no need to forward the plane commit calls to
> the driver, so use the DRM core infrastructure to skip them with a
> detailed comment to explain why the check must still be kept in the
> driver.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v3:
> 
> - Reworded commit message
> ---
>  drivers/gpu/drm/omapdrm/omap_crtc.c | 8 +++++++-
>  drivers/gpu/drm/omapdrm/omap_drv.c  | 3 ++-
>  2 files changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
> index 42c3b44f9689..2832dbffd873 100644
> --- a/drivers/gpu/drm/omapdrm/omap_crtc.c
> +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
> @@ -414,7 +414,13 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
>  		dispc_mgr_set_gamma(omap_crtc->channel, lut, length);
>  	}
>  
> -	/* Only flush the CRTC if it is currently enabled. */
> +	/*
> +	 * Only flush the CRTC if it is currently enabled. CRTCs that require a
> +	 * mode set are disabled prior plane updates and enabled afterwards.
> +	 * They are thus not active (regardless of what their CRTC core state
> +	 * reports) and the DRM core could thus call this function even though
> +	 * the CRTC is currently disabled. Do nothing in that case.
> +	 */
>  	if (!omap_crtc->enabled)
>  		return;
>  
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> index 6faba13c8e41..0a2d461d62cf 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -96,7 +96,8 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
>  	dispc_runtime_get();
>  
>  	drm_atomic_helper_commit_modeset_disables(dev, old_state);
> -	drm_atomic_helper_commit_planes(dev, old_state, 0);
> +	drm_atomic_helper_commit_planes(dev, old_state,
> +					DRM_PLANE_COMMIT_ACTIVE_ONLY);
>  	drm_atomic_helper_commit_modeset_enables(dev, old_state);

Just to make sure. "ACTIVE" in this context means a crtc that's already
enabled, or will be enabled at the
drm_atomic_helper_commit_modeset_enables() call?

If so:

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 10/22] drm: omapdrm: Let the DRM core skip plane commit on inactive CRTCs
  2016-12-14 10:43   ` Tomi Valkeinen
@ 2016-12-14 11:26     ` Laurent Pinchart
  0 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14 11:26 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: dri-devel

Hi Tomi,

On Wednesday 14 Dec 2016 12:43:54 Tomi Valkeinen wrote:
> On 14/12/16 02:27, Laurent Pinchart wrote:
> > The DRM core supports skipping plane update for inactive CRTCs for
> > hardware that don't need it or can't cope with it. That's our case, and
> > the driver already skips flushing planes on inactice CRTCs.
> > 
> > We can't remove the check from the driver, as active CRTCs are disabled
> > at the hardware level when an atomic flush is performed if a mode set is
> > pending. There's however no need to forward the plane commit calls to
> > the driver, so use the DRM core infrastructure to skip them with a
> > detailed comment to explain why the check must still be kept in the
> > driver.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > Changes since v3:
> > 
> > - Reworded commit message
> > ---
> > 
> >  drivers/gpu/drm/omapdrm/omap_crtc.c | 8 +++++++-
> >  drivers/gpu/drm/omapdrm/omap_drv.c  | 3 ++-
> >  2 files changed, 9 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c
> > b/drivers/gpu/drm/omapdrm/omap_crtc.c index 42c3b44f9689..2832dbffd873
> > 100644
> > --- a/drivers/gpu/drm/omapdrm/omap_crtc.c
> > +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
> > @@ -414,7 +414,13 @@ static void omap_crtc_atomic_flush(struct drm_crtc
> > *crtc,> 
> >  		dispc_mgr_set_gamma(omap_crtc->channel, lut, length);
> >  	}
> > 
> > -	/* Only flush the CRTC if it is currently enabled. */
> > +	/*
> > +	 * Only flush the CRTC if it is currently enabled. CRTCs that require
> > a
> > +	 * mode set are disabled prior plane updates and enabled afterwards.
> > +	 * They are thus not active (regardless of what their CRTC core state
> > +	 * reports) and the DRM core could thus call this function even though
> > +	 * the CRTC is currently disabled. Do nothing in that case.
> > +	 */
> >  	if (!omap_crtc->enabled)
> >  		return;
> > 
> > diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c
> > b/drivers/gpu/drm/omapdrm/omap_drv.c index 6faba13c8e41..0a2d461d62cf
> > 100644
> > --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> > +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> > @@ -96,7 +96,8 @@ static void omap_atomic_complete(struct
> > omap_atomic_state_commit *commit)
> >  	dispc_runtime_get();
> >  	
> >  	drm_atomic_helper_commit_modeset_disables(dev, old_state);
> > -	drm_atomic_helper_commit_planes(dev, old_state, 0);
> > +	drm_atomic_helper_commit_planes(dev, old_state,
> > +					DRM_PLANE_COMMIT_ACTIVE_ONLY);
> >  	drm_atomic_helper_commit_modeset_enables(dev, old_state);
> 
> Just to make sure. "ACTIVE" in this context means a crtc that's already
> enabled, or will be enabled at the
> drm_atomic_helper_commit_modeset_enables() call?

Correct, it covers both.

> If so:
> 
> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 06/22] drm: omapdrm: Handle FIFO underflow IRQs internally
  2016-12-14 10:22   ` Tomi Valkeinen
@ 2016-12-14 11:48     ` Laurent Pinchart
  2016-12-14 13:13       ` Tomi Valkeinen
  2016-12-15  9:02       ` Tomi Valkeinen
  0 siblings, 2 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14 11:48 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: dri-devel

Hi Tomi,

On Wednesday 14 Dec 2016 12:22:29 Tomi Valkeinen wrote:
> On 14/12/16 02:27, Laurent Pinchart wrote:
> > As the FIFO underflow IRQ handler just prints an error message to the
> > kernel log, simplify the code by not registering one IRQ handler per
> > plane but print the messages directly from the main IRQ handler.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> > ---
> > 
> > +static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
> > +				    u32 irqstatus)
> > +{
> > +	static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
> > +				      DEFAULT_RATELIMIT_BURST);
> > +	static const struct {
> > +		const char *name;
> > +		u32 mask;
> > +	} sources[] = {
> > +		{ "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW },
> > +		{ "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW },
> > +		{ "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW },
> > +		{ "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW },
> > +	};
> > +
> > +	const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW
> > +		       | DISPC_IRQ_VID1_FIFO_UNDERFLOW
> > +		       | DISPC_IRQ_VID2_FIFO_UNDERFLOW
> > +		       | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
> > +	unsigned int i;
> > +
> > +	spin_lock(&list_lock);
> > +	irqstatus &= priv->irq_mask & mask;
> > +	spin_unlock(&list_lock);
> > +
> > +	if (!irqstatus)
> > +		return;
> 
> This is called every time we get any DSS interrupt, so I think it would
> be good to have a fast-path here without the lock: irqstatus & mask.
>
> Or maybe store the enabled underflow irq bits separately from irq_mask,
> as the underflow bits are never changed after the initial setup, and
> then there's no need for locking.

I'd prefer going for the former, but I'm a bit concerned that an IRQ bit 
defined as FIFO overflow on one platform could be defined as something else on 
another platform and be mistaken.

Given that we already take the same lock in the IRQ handler to call the wait 
handlers, do you think this is really an issue ?

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 00/22] OMAP DRM fixes and improvements
  2016-12-14  8:48 ` [PATCH v4 00/22] OMAP DRM fixes and improvements Tomi Valkeinen
@ 2016-12-14 11:50   ` Laurent Pinchart
  0 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-14 11:50 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: dri-devel

Hi Tomi,

On Wednesday 14 Dec 2016 10:48:06 Tomi Valkeinen wrote:
> On 14/12/16 02:27, Laurent Pinchart wrote:
> > Hello,
> > 
> > Here's the fourth version of my current stack of pending patches for the
> > omapdrm driver.
> > 
> > All comments received for v3 have been considered and patches updated
> > where applicable. Patches 21/22 and 22/22 have been added, individual
> > changelogs are available in all the patches when they have been modified.
> > 
> > The most notable change in this series is still the rework of the IRQ
> > handling code (patches 06/22 to 19/22) that, beside simplifying the code,
> > ensures that the vblank count and timestamp get updated properly in order
> > to be reported to userspace.
> > 
> > The series is based on top of Dave's drm-next branch.
> 
> I got the following when unloading omapdrm modules, AM5 EVM with two
> displays:

This should be fixed by "[PATCH] drm: Move vblank cleanup from unregister to 
release" that I posted earlier today.

> 
> [  758.762147] ------------[ cut here ]------------
> [  758.767157] WARNING: CPU: 1 PID: 314 at drivers/gpu/drm/drm_irq.c:349
> drm_vblank_cleanup+0x5c/0x94 [drm] [  758.781401] Modules linked in:
> omapdrm(-) drm_kms_helper drm panel_dsi_cm panel_dpi connector_analog_tv
> connector_dvi connecto r_hdmi encoder_tpd12s015 encoder_tfp410 omapdss
> cfbfillrect cfbimgblt cfbcopyarea [last unloaded: omapdss_base] [ 
> 758.803761] CPU: 1 PID: 314 Comm: rmmod Not tainted
> 4.9.0-rc8-00106-g8df5349534c6 #53 [  758.811631] Hardware name: Generic
> DRA74X (Flattened Device Tree) [  758.817755] Backtrace:
> [  758.820240] [<c010d8e0>] (dump_backtrace) from [<c010db8c>]
> (show_stack+0x18/0x1c) [  758.827851]  r7:c0d830d8 r6:60030013 r5:00000000
> r4:c0d830d8
> [  758.833546] [<c010db74>] (show_stack) from [<c04d8668>]
> (dump_stack+0xa8/0xdc) [  758.840813] [<c04d85c0>] (dump_stack) from
> [<c013c660>] (__warn+0xdc/0x108) [  758.847814]  r9:bf1fefc0 r8:0000015d
> r7:00000009 r6:bf229b84 r5:00000000 r4:00000000 [  758.855602] [<c013c584>]
> (__warn) from [<c013c740>] (warn_slowpath_null+0x28/0x30) [  758.863230] 
> r9:0000015d r8:bf229b84 r7:ee145000 r6:00000000 r5:00000000 r4:ed22aa00 .[ 
> 758.871173] [<c013c718>] (warn_slowpath_null) from [<bf1fefc0>]
> (drm_vblank_cleanup+0x5c/0x94 [drm]) [  758.880586] [<bf1fef64>]
> (drm_vblank_cleanup [drm]) from [<bf200760>] (drm_dev_unregister+0x58/0xbc
> [drm]) [  758.890291]  r9:ed3b4000 r8:c0ddb380 r7:00000000 r6:ee145000
> r5:ee145000 r4:ee145000 [  758.898201] [<bf200708>] (drm_dev_unregister
> [drm]) from [<bf2ab26c>] (pdev_remove+0x2c/0x90 [omapdrm]) [  758.907643] 
> r7:00000000 r6:c0d0c25c r5:ed233000 r4:ee145000
> [  758.913357] [<bf2ab240>] (pdev_remove [omapdrm]) from [<c05a1918>]
> (platform_drv_remove+0x2c/0x44) [  758.922362]  r5:c0d0c228 r4:c0d0c228
> [  758.925964] [<c05a18ec>] (platform_drv_remove) from [<c059ed24>]
> (__device_release_driver+0x90/0x12c) [  758.935229]  r5:bf2b64e4
> r4:c0d0c228
> [  758.938829] [<c059ec94>] (__device_release_driver) from [<c059f9b0>]
> (driver_detach+0xc0/0xc4) [  758.947484]  r5:bf2b64e4 r4:c0d0c228
> [  758.951084] [<c059f8f0>] (driver_detach) from [<c059e764>]
> (bus_remove_driver+0x64/0xdc) [  758.959217]  r7:c0b3bbfc r6:c0ddb368
> r5:bf2b42e4 r4:bf2b64e4
> [  758.964911] [<c059e700>] (bus_remove_driver) from [<c05a079c>]
> (driver_unregister+0x30/0x50) [  758.973390]  r5:bf2b42e4 r4:bf2b64e4
> [  758.976991] [<c05a076c>] (driver_unregister) from [<c05a1a3c>]
> (platform_unregister_drivers+0x3c/0x74) [  758.986343]  r5:bf2b42e4
> r4:00000000
> [  758.989961] [<c05a1a00>] (platform_unregister_drivers) from [<bf2b42b8>]
> (omap_drm_fini+0x28/0x38 [omapdrm]) [  758.999841]  r9:ed3b4000 r8:c0108c04
> r7:00000081 r6:00000800 r5:0003cd4c r4:bf2b6800 [  759.007649] [<bf2b4290>]
> (omap_drm_fini [omapdrm]) from [<c01e63d4>] (SyS_delete_module+0x144/0x21c)
> [  759.016835] [<c01e6290>] (SyS_delete_module) from [<c0108a60>]
> (ret_fast_syscall+0x0/0x1c) [  759.025142]  r6:bec63c10 r5:0003cd10
> r4:bec63dfc
> [  759.029902] ---[ end trace ebaa3f100ebbc054 ]---
> [  759.036433] ------------[ cut here ]------------
> [  759.041394] WARNING: CPU: 1 PID: 314 at drivers/gpu/drm/drm_irq.c:349
> drm_vblank_cleanup+0x5c/0x94 [drm] [  759.050963] Modules linked in:
> omapdrm(-) drm_kms_helper drm panel_dsi_cm panel_dpi connector_analog_tv
> connector_dvi connecto r_hdmi encoder_tpd12s015 encoder_tfp410 omapdss
> cfbfillrect cfbimgblt cfbcopyarea [last unloaded: omapdss_base] [ 
> 759.072372] CPU: 1 PID: 314 Comm: rmmod Tainted: G        W      
> 4.9.0-rc8-00106-g8df5349534c6 #53 [  759.081462] Hardware name: Generic
> DRA74X (Flattened Device Tree) [  759.087584] Backtrace:
> [  759.090064] [<c010d8e0>] (dump_backtrace) from [<c010db8c>]
> (show_stack+0x18/0x1c) [  759.097675]  r7:c0d830d8 r6:60030013 r5:00000000
> r4:c0d830d8
> [  759.103368] [<c010db74>] (show_stack) from [<c04d8668>]
> (dump_stack+0xa8/0xdc) [  759.110633] [<c04d85c0>] (dump_stack) from
> [<c013c660>] (__warn+0xdc/0x108) [  759.117634]  r9:bf1fefc0 r8:0000015d
> r7:00000009 r6:bf229b84 r5:00000000 r4:00000000 [  759.125421] [<c013c584>]
> (__warn) from [<c013c740>] (warn_slowpath_null+0x28/0x30) [  759.133033] 
> r9:0000015d r8:bf229b84 r7:ee145000 r6:00000001 r5:000000c8 r4:ed22aac8 /[ 
> 759.140927] [<c013c718>] (warn_slowpath_null) from [<bf1fefc0>]
> (drm_vblank_cleanup+0x5c/0x94 [drm]) [  759.150391] [<bf1fef64>]
> (drm_vblank_cleanup [drm]) from [<bf200760>] (drm_dev_unregister+0x58/0xbc
> [drm]) [  759.160097]  r9:ed3b4000 r8:c0ddb380 r7:00000000 r6:ee145000
> r5:ee145000 r4:ee145000 [  759.168006] [<bf200708>] (drm_dev_unregister
> [drm]) from [<bf2ab26c>] (pdev_remove+0x2c/0x90 [omapdrm]) [  759.177448] 
> r7:00000000 r6:c0d0c25c r5:ed233000 r4:ee145000
> [  759.183161] [<bf2ab240>] (pdev_remove [omapdrm]) from [<c05a1918>]
> (platform_drv_remove+0x2c/0x44) [  759.192164]  r5:c0d0c228 r4:c0d0c228
> [  759.195766] [<c05a18ec>] (platform_drv_remove) from [<c059ed24>]
> (__device_release_driver+0x90/0x12c) [  759.205031]  r5:bf2b64e4
> r4:c0d0c228
> [  759.208632] [<c059ec94>] (__device_release_driver) from [<c059f9b0>]
> (driver_detach+0xc0/0xc4) [  759.217287]  r5:bf2b64e4 r4:c0d0c228
> [  759.220887] [<c059f8f0>] (driver_detach) from [<c059e764>]
> (bus_remove_driver+0x64/0xdc) [  759.229021]  r7:c0b3bbfc r6:c0ddb368
> r5:bf2b42e4 r4:bf2b64e4
> [  759.234715] [<c059e700>] (bus_remove_driver) from [<c05a079c>]
> (driver_unregister+0x30/0x50) [  759.243196]  r5:bf2b42e4 r4:bf2b64e4
> [  759.246797] [<c05a076c>] (driver_unregister) from [<c05a1a3c>]
> (platform_unregister_drivers+0x3c/0x74) [  759.256151]  r5:bf2b42e4
> r4:00000000
> [  759.259770] [<c05a1a00>] (platform_unregister_drivers) from [<bf2b42b8>]
> (omap_drm_fini+0x28/0x38 [omapdrm]) [  759.269650]  r9:ed3b4000 r8:c0108c04
> r7:00000081 r6:00000800 r5:0003cd4c r4:bf2b6800 [  759.277456] [<bf2b4290>]
> (omap_drm_fini [omapdrm]) from [<c01e63d4>] (SyS_delete_module+0x144/0x21c)
> [  759.286641] [<c01e6290>] (SyS_delete_module) from [<c0108a60>]
> (ret_fast_syscall+0x0/0x1c) [  759.294948]  r6:bec63c10 r5:0003cd10
> r4:bec63dfc
> [  759.299701] ---[ end trace ebaa3f100ebbc055 ]---
> [  759.309098] ------------[ cut here ]------------
> [  759.313879] WARNING: CPU: 0 PID: 7 at drivers/gpu/drm/drm_irq.c:1708
> drm_handle_vblank+0x398/0x3c8 [drm] [  759.323401] Modules linked in:
> omapdrm(-) drm_kms_helper drm panel_dsi_cm panel_dpi connector_analog_tv
> connector_dvi connecto r_hdmi encoder_tpd12s015 encoder_tfp410 omapdss
> cfbfillrect cfbimgblt cfbcopyarea [last unloaded: omapdss_base] [ 
> 759.344721] CPU: 0 PID: 7 Comm: rcu_preempt Tainted: G        W      
> 4.9.0-rc8-00106-g8df5349534c6 #53 [  759.354155] Hardware name: Generic
> DRA74X (Flattened Device Tree) [  759.360276] Backtrace:
> [  759.362752] [<c010d8e0>] (dump_backtrace) from [<c010db8c>]
> (show_stack+0x18/0x1c) [  759.370359]  r7:c0d830d8 r6:600f0193 r5:00000000
> r4:c0d830d8
> [  759.376049] [<c010db74>] (show_stack) from [<c04d8668>]
> (dump_stack+0xa8/0xdc) [  759.383312] [<c04d85c0>] (dump_stack) from
> [<c013c660>] (__warn+0xdc/0x108) [  759.390310]  r9:bf1fede4 r8:000006ac
> r7:00000009 r6:bf229b84 r5:00000000 r4:00000000 [  759.398094] [<c013c584>]
> (__warn) from [<c013c740>] (warn_slowpath_null+0x28/0x30) [  759.405701] 
> r9:ee145000 r8:ee145000 r7:00000001 r6:ed233000 r5:00000802 r4:ed22aac8 [ 
> 759.413589] [<c013c718>] (warn_slowpath_null) from [<bf1fede4>]
> (drm_handle_vblank+0x398/0x3c8 [drm]) [  759.422980] [<bf1fea4c>]
> (drm_handle_vblank [drm]) from [<bf2ac188>] (omap_irq_handler+0x88/0x210
> [omapdrm]) [  759.432856]  r10:00000000 r9:ee145000 r8:ed23300c r7:ed0ae800
> r6:ed233000 r5:00000802 [  759.440719]  r4:00000001
> [  759.443370] [<bf2ac100>] (omap_irq_handler [omapdrm]) from [<bf1757a8>]
> (dispc_irq_handler+0x34/0x3c [omapdss]) [  759.453507]  r10:c0d0512c
> r9:0000015e r8:c0d05db0 r7:ee0ea000 r6:c0d836b0 r5:ee0ea000 [  759.461372] 
> r4:ed19db80
> [  759.464002] [<bf175774>] (dispc_irq_handler [omapdss]) from [<c01afd74>]
> (__handle_irq_event_percpu+0x54/0x488) [  759.474142] [<c01afd20>]
> (__handle_irq_event_percpu) from [<c01b01cc>]
> (handle_irq_event_percpu+0x24/0x60) [  759.483841]  r10:0000015e
> r9:00000001 r8:c0d05db0 r7:ee0ea000 r6:c0d836b0 r5:ee336200 [  759.491706] 
> r4:ee336200
> [  759.494256] [<c01b01a8>] (handle_irq_event_percpu) from [<c01b0248>]
> (handle_irq_event+0x40/0x64) [  759.503169]  r5:ee336260 r4:ee336200
> [  759.506768] [<c01b0208>] (handle_irq_event) from [<c01b3b30>]
> (handle_fasteoi_irq+0xec/0x1cc) [  759.515332]  r7:ee0ea000 r6:c0d836b0
> r5:ee336260 r4:ee336200
> [  759.521021] [<c01b3a44>] (handle_fasteoi_irq) from [<c01aeeec>]
> (generic_handle_irq+0x28/0x3c) [  759.529674]  r9:00000001 r8:00000000
> r7:c0d05db0 r6:ee0ea000 r5:c0c7c274 r4:c0c7c274 [  759.537458] [<c01aeec4>]
> (generic_handle_irq) from [<c01af4f8>] (__handle_domain_irq+0x98/0x134) [ 
> 759.546288] [<c01af460>] (__handle_domain_irq) from [<c01015d4>]
> (gic_handle_irq+0x58/0xbc) [  759.554679]  r10:c0d05fe4 r9:fa212000
> r8:c0d836a0 r7:ee0ebd38 r6:000003ff r5:000003eb [  759.562544]  r4:fa21200c
> [  759.565096] [<c010157c>] (gic_handle_irq) from [<c08d6e30>]
> (__irq_svc+0x70/0xb0) [  759.572612] Exception stack(0xee0ebd38 to
> 0xee0ebd80)
> [  759.577688] bd20:                                                      
> 00000001 00000001 [  759.585907] bd40: 00000000 ee0e8e80 eed8b080 00000000
> c0d08980 00000000 00000001 ee0e8e80 [  759.594123] bd60: c08cfa70 ee0ebd9c
> ee0ebd58 ee0ebd88 c019f9a0 c08d6458 200f0013 ffffffff [  759.602341] 
> r10:c08cfa70 r9:ee0ea000 r8:00000001 r7:ee0ebd6c r6:ffffffff r5:200f0013 [ 
> 759.610204]  r4:c08d6458
> [  759.612756] [<c08d6428>] (_raw_spin_unlock_irq) from [<c016c6d4>]
> (finish_task_switch+0xdc/0x284) [  759.621669]  r5:00000000 r4:eed8b080
> [  759.625266] [<c016c5f8>] (finish_task_switch) from [<c08cfa70>]
> (__schedule+0x3fc/0xd3c) [  759.633396]  r10:ee0e9180 r9:00000000
> r8:ed084240 r7:00002f1f r6:c0d08980 r5:ee0e8e80 [  759.641261]  r4:eed8b090
> [  759.643810] [<c08cf674>] (__schedule) from [<c08d0408>]
> (schedule+0x58/0xb8) [  759.650894]  r10:00000000 r9:000008b9 r8:eed865c0
> r7:c0d04900 r6:00000000 r5:00000001 [  759.658759]  r4:ee0ea000
> [  759.661308] [<c08d03b0>] (schedule) from [<c08d542c>]
> (schedule_timeout+0x208/0x4fc) [  759.669088]  r7:c0d04900 r6:eed865c0
> r5:ee0ebe88 r4:0000b35a
> [  759.674778] [<c08d5224>] (schedule_timeout) from [<c01bf228>]
> (rcu_gp_kthread+0x5a4/0x974) [  759.683086]  r10:00000001 r9:000008b9
> r8:00000000 r7:c0d45210 r6:c0d45238 r5:00000001 [  759.690953]  r4:c0d44f80
> [  759.693502] [<c01bec84>] (rcu_gp_kthread) from [<c0163890>]
> (kthread+0xe4/0x108) [  759.700931]  r7:c01bec84
> [  759.703482] [<c01637ac>] (kthread) from [<c0108af0>]
> (ret_from_fork+0x14/0x24) [  759.710738]  r7:00000000 r6:00000000
> r5:c01637ac r4:ee088900
> [  759.716423] ---[ end trace ebaa3f100ebbc056 ]---
> ^H[  759.789292] ------------[ cut here ]------------
> [  759.794068] WARNING: CPU: 1 PID: 314 at drivers/gpu/drm/drm_irq.c:1278
> drm_crtc_vblank_off+0x1b0/0x1cc [drm] [  759.804252] Modules linked in:
> omapdrm(-) drm_kms_helper drm panel_dsi_cm panel_dpi connector_analog_tv
> connector_dvi connecto r_hdmi encoder_tpd12s015 encoder_tfp410 omapdss
> cfbfillrect cfbimgblt cfbcopyarea [last unloaded: omapdss_base] [ 
> 759.826582] CPU: 1 PID: 314 Comm: rmmod Tainted: G        W      
> 4.9.0-rc8-00106-g8df5349534c6 #53 [  759.835673] Hardware name: Generic
> DRA74X (Flattened Device Tree) [  759.841797] Backtrace:
> [  759.844276] [<c010d8e0>] (dump_backtrace) from [<c010db8c>]
> (show_stack+0x18/0x1c) [  759.851888]  r7:c0d830d8 r6:600e0013 r5:00000000
> r4:c0d830d8
> [  759.857581] [<c010db74>] (show_stack) from [<c04d8668>]
> (dump_stack+0xa8/0xdc) [  759.864845] [<c04d85c0>] (dump_stack) from
> [<c013c660>] (__warn+0xdc/0x108) [  759.871846]  r9:bf1fea30 r8:000004fe
> r7:00000009 r6:bf229b84 r5:00000000 r4:00000000 [  759.879632] [<c013c584>]
> (__warn) from [<c013c740>] (warn_slowpath_null+0x28/0x30) [  759.887244] 
> r9:ee145000 r8:bf2b4ad0 r7:00000000 r6:ed23f200 r5:00000000 r4:ed22aa00 [ 
> 759.895139] [<c013c718>] (warn_slowpath_null) from [<bf1fea30>]
> (drm_crtc_vblank_off+0x1b0/0x1cc [drm]) [  759.904707] [<bf1fe880>]
> (drm_crtc_vblank_off [drm]) from [<bf2ace38>] (omap_crtc_disable+0x2c/0x38
> [omapdrm]) [  759.914761]  r10:bf286140 r9:bf286110 r8:bf2b4ad0 r7:ed0c8000
> r6:ed23f200 r5:00000000 [  759.922628]  r4:ed0c8000
> [  759.925256] [<bf2ace0c>] (omap_crtc_disable [omapdrm]) from [<bf27aaec>]
> (drm_atomic_helper_commit_modeset_disables+0x1c0/0x41 4 [drm_kms_helper])
> [  759.938360]  r5:00000000 r4:ed19db00
> [  759.942026] [<bf27a92c>] (drm_atomic_helper_commit_modeset_disables
> [drm_kms_helper]) from [<bf2ab528>] (omap_atomic_complete+ 0x2c/0x15c
> [omapdrm])
> [  759.955305]  r10:bf22c188 r9:00000000 r8:ed233000 r7:ed19d780 r6:ee145000
> r5:ed19db00 [  759.963173]  r4:ed233128
> [  759.965759] [<bf2ab4fc>] (omap_atomic_complete [omapdrm]) from
> [<bf2ab7d8>] (omap_atomic_commit+0x180/0x268 [omapdrm]) [  759.976508] 
> r9:00000000 r8:00000000 r7:ed233000 r6:ed19db00 r5:ed19d780 r4:ed233128 [ 
> 759.984420] [<bf2ab658>] (omap_atomic_commit [omapdrm]) from [<bf210d54>]
> (drm_atomic_commit+0x54/0x60 [drm]) [  759.994386]  r10:bf22c188
> r9:bf22c1b8 r8:ee145000 r7:ed3b5e04 r6:ee145000 r5:ed19db00 [  760.002254] 
> r4:00000000
> [  760.004960] [<bf210d00>] (drm_atomic_commit [drm]) from [<bf27dffc>]
> (drm_atomic_helper_set_config+0x80/0xd8 [drm_kms_helper]) [  760.016406] 
> r7:ed3b5e04 r6:ed0c8000 r5:00000000 r4:ed19db00
> [  760.022250] [<bf27df7c>] (drm_atomic_helper_set_config [drm_kms_helper])
> from [<bf2046b8>] (drm_mode_set_config_internal+0x6c/ 0xfc [drm])
> [  760.034656]  r7:ee14548c r6:ee145480 r5:ed0c8000 r4:00000000
> [  760.040558] [<bf20464c>] (drm_mode_set_config_internal [drm]) from
> [<bf204780>] (drm_crtc_force_disable+0x38/0x40 [drm]) [  760.051481] 
> r7:ee14548c r6:ee145480 r5:ed24f800 r4:ed0c8000
> [  760.057384] [<bf204748>] (drm_crtc_force_disable [drm]) from [<bf212e94>]
> (drm_framebuffer_remove+0xd0/0x110 [drm]) [  760.067997] [<bf212dc4>]
> (drm_framebuffer_remove [drm]) from [<bf2b4274>] (omap_fbdev_free+0x60/0x7c
> [omapdrm]) [  760.078138]  r10:00000000 r9:ed3b4000 r8:c0ddb380 r7:00000000
> r6:c0d0c25c r5:ed233000 [  760.086007]  r4:ed285200 r3:00000001
> [  760.089639] [<bf2b4214>] (omap_fbdev_free [omapdrm]) from [<bf2ab288>]
> (pdev_remove+0x48/0x90 [omapdrm]) [  760.099165]  r5:ed233000 r4:ee145000
> [  760.102784] [<bf2ab240>] (pdev_remove [omapdrm]) from [<c05a1918>]
> (platform_drv_remove+0x2c/0x44) [  760.111788]  r5:c0d0c228 r4:c0d0c228
> [  760.115390] [<c05a18ec>] (platform_drv_remove) from [<c059ed24>]
> (__device_release_driver+0x90/0x12c) [  760.124653]  r5:bf2b64e4
> r4:c0d0c228
> [  760.128252] [<c059ec94>] (__device_release_driver) from [<c059f9b0>]
> (driver_detach+0xc0/0xc4) [  760.136907]  r5:bf2b64e4 r4:c0d0c228
> [  760.140507] [<c059f8f0>] (driver_detach) from [<c059e764>]
> (bus_remove_driver+0x64/0xdc) [  760.148638]  r7:c0b3bbfc r6:c0ddb368
> r5:bf2b42e4 r4:bf2b64e4
> [  760.154331] [<c059e700>] (bus_remove_driver) from [<c05a079c>]
> (driver_unregister+0x30/0x50) [  760.162810]  r5:bf2b42e4 r4:bf2b64e4
> [  760.166411] [<c05a076c>] (driver_unregister) from [<c05a1a3c>]
> (platform_unregister_drivers+0x3c/0x74) [  760.175771]  r5:bf2b42e4
> r4:00000000
> [  760.179389] [<c05a1a00>] (platform_unregister_drivers) from [<bf2b42b8>]
> (omap_drm_fini+0x28/0x38 [omapdrm]) [  760.189267]  r9:ed3b4000 r8:c0108c04
> r7:00000081 r6:00000800 r5:0003cd4c r4:bf2b6800 [  760.197073] [<bf2b4290>]
> (omap_drm_fini [omapdrm]) from [<c01e63d4>] (SyS_delete_module+0x144/0x21c)
> [  760.206256] [<c01e6290>] (SyS_delete_module) from [<c0108a60>]
> (ret_fast_syscall+0x0/0x1c) [  760.214562]  r6:bec63c10 r5:0003cd10
> r4:bec63dfc
> ^H^H[  760.219458] ---[ end trace ebaa3f100ebbc057 ]---
> [  760.233226] ------------[ cut here ]------------
> ^H[  760.237992] WARNING: CPU: 1 PID: 314 at drivers/gpu/drm/drm_irq.c:1278
> drm_crtc_vblank_off+0x1b0/0x1cc [drm] [  760.248043] Modules linked in:
> omapdrm(-) drm_kms_helper drm panel_dsi_cm panel_dpi connector_analog_tv
> connector_dvi connecto r_hdmi encoder_tpd12s015 encoder_tfp410 omapdss
> cfbfillrect^H cfbimgblt cfbcopyarea [last unloaded: omapdss_base] [ 
> 760.269659] CPU: 1 PID: 314 Comm: rmmod Tainted: G        W      
> 4.9.0-rc8-00106-g8df5349534c6 #53 [  760.278750] Hardware name: Generic
> DRA74X (Flattened Device Tree) [  760.284873] Backtrace:
> [  760.287353] [<c010d8e0>] (dump_backtrace) from [<c010db8c>]
> (show_stack+0x18/0x1c) [  760.294965]  r7:c0d830d8 r6:600e0013 r5:00000000
> r4:c0d830d8
> [  760.300660] [<c010db74>] (show_stack) from [<c04d8668>]
> (dump_stack+0xa8/0xdc) ^H[  760.307943] [<c04d85c0>] (dump_stack) from
> [<c013c660>] (__warn+0xdc/0x108) [  760.315115]  r9:bf1fea30 r8:000004fe
> r7:00000009 r6:bf229b84 r5:00000000 r4:00000000 [  760.322906] [<c013c584>]
> (__warn) from [<c013c740>] (warn_slowpath_null+0x28/0x30) [  760.330533] 
> r9:ee145000 r8:bf2b4ad0 r7:00000001 r6:ed23f800 r5:00000001 r4:ed22aac8 ^H[
>  760.338427] [<c013c718>] (warn_slowpath_null) from [<bf1fea30>]
> (drm_crtc_vblank_off+0x1b0/0x1cc [drm]) [  760.348059] [<bf1fe880>]
> (drm_crtc_vblank_off [drm]) from [<bf2ace38>] (omap_crtc_disable+0x2c/0x38
> [omapdrm]) [  760.358112]  r10:bf286140 r9:bf286110 r8:bf2b4ad0 r7:ed0ae800
> r6:ed23f800 r5:00000001 [  760.365981]  r4:ed0ae800
> [  760.368604] [<bf2ace0c>] (omap_crtc_disable [omapdrm]) from [<bf27aaec>]
> (drm_atomic_helper_commit_modeset_disables+0x1c0/0x41 4 [drm_kms_helper])
> [  760.381709]  r5:00000001 r4:ed19db00
> ^H[  760.385374] [<bf27a92c>] (drm_atomic_helper_commit_modeset_disables
> [drm_kms_helper]) from [<bf2ab528>] (omap_atomic_complet e+0x2c/0x15c
> [omapdrm])
> [  760.398782]  r10:bf22c188 r9:00000000 r8:ed233000 r7:ed19d780 r6:ee145000
> r5:ed19db00 [  760.406650]  r4:ed233128
> ^H[  760.409235] [<bf2ab4fc>] (omap_atomic_complete [omapdrm]) from
> [<bf2ab7d8>] (omap_atomic_commit+0x180/0x268 [omapdrm]) [  760.420164] 
> r9:00000000 r8:00000000 r7:ed233000 r6:ed19db00 r5:ed19d780 r4:ed233128 ^H[
>  760.428075] [<bf2ab658>] (omap_atomic_commit [omapdrm]) from [<bf210d54>]
> (drm_atomic_commit+0x54/0x60 [drm]) [  760.438105]  r10:bf22c188
> r9:bf22c1b8 r8:ee145000 r7:ed3b5e04 r6:ee145000 r5:ed19db00 [  760.445974] 
> r4:00000000
> ^H[  760.448691] [<bf210d00>] (drm_atomic_commit [drm]) from [<bf27dffc>]
> (drm_atomic_helper_set_config+0x80/0xd8 [drm_kms_helper ])
> [  760.460160]  r7:ed3b5e04 r6:ed0ae800 r5:00000000 r4:ed19db00
> [  760.466007] [<bf27df7c>] (drm_atomic_helper_set_config [drm_kms_helper])
> from [<bf2046b8>] (drm_mode_set_config_internal+0x6c/ 0xfc [drm])
> [  760.478413]  r7:ee14548c r6:ee145480 r5:ed0ae800 r4:00000000
> ^H[  760.484317] [<bf20464c>] (drm_mode_set_config_internal [drm]) from
> [<bf204780>] (drm_crtc_force_disable+0x38/0x40 [drm]) [  760.495293] 
> r7:ee14548c r6:ee145480 r5:ed24f800 r4:ed0ae800
> [  760.501196] [<bf204748>] (drm_crtc_force_disable [drm]) from [<bf212e94>]
> (drm_framebuffer_remove+0xd0/0x110 [drm]) ^H[  760.511807] [<bf212dc4>]
> (drm_framebuffer_remove [drm]) from [<bf2b4274>] (omap_fbdev_free+0x60/0x7c
> [omapdrm]) [  760.522090]  r10:00000000 r9:ed3b4000 r8:c0ddb380 r7:00000000
> r6:c0d0c25c r5:ed233000 [  760.529959]  r4:ed285200 r3:00000001
> [  760.533591] [<bf2b4214>] (omap_fbdev_free [omapdrm]) from [<bf2ab288>]
> (pdev_remove+0x48/0x90 [omapdrm]) [  760.543118]  r5:ed233000 r4:ee145000
> ^H[  760.546738] [<bf2ab240>] (pdev_remove [omapdrm]) from [<c05a1918>]
> (platform_drv_remove+0x2c/0x44) [  760.555893]  r5:c0d0c228 r4:c0d0c228
> [  760.559495] [<c05a18ec>] (platform_drv_remove) from [<c059ed24>]
> (__device_release_driver+0x90/0x12c) [  760.568760]  r5:bf2b64e4
> r4:c0d0c228
> [  760.572379] [<c059ec94>] (__device_release_driver) from [<c059f9b0>]
> (driver_detach+0xc0/0xc4) [  760.581033]  r5:bf2b64e4 r4:c0d0c228
> ^H[  760.584633] [<c059f8f0>] (driver_detach) from [<c059e764>]
> (bus_remove_driver+0x64/0xdc) [  760.592936]  r7:c0b3bbfc r6:c0ddb368
> r5:bf2b42e4 r4:bf2b64e4
> [  760.598627] [<c059e700>] (bus_remove_driver) from [<c05a079c>]
> (driver_unregister+0x30/0x50) [  760.607106]  r5:bf2b42e4 r4:bf2b64e4
> [  760.610707] [<c05a076c>] (driver_unregister) from [<c05a1a3c>]
> (platform_unregister_drivers+0x3c/0x74) [  760.620078]  r5:bf2b42e4
> r4:00000000
> ^H[  760.623697] [<c05a1a00>] (platform_unregister_drivers) from
> [<bf2b42b8>] (omap_drm_fini+0x28/0x38 [omapdrm]) [  760.633730] 
> r9:ed3b4000 r8:c0108c04 r7:00000081 r6:00000800 r5:0003cd4c r4:bf2b6800 [ 
> 760.641536] [<bf2b4290>] (omap_drm_fini [omapdrm]) from [<c01e63d4>]
> (SyS_delete_module+0x144/0x21c) [  760.650725] [<c01e6290>]
> (SyS_delete_module) from [<c0108a60>] (ret_fast_syscall+0x0/0x1c) [ 
> 760.659033]  r6:bec63c10 r5:0003cd10 r4:bec63dfc
> ^H[  760.663832] ---[ end trace ebaa3f100ebbc058 ]---

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 06/22] drm: omapdrm: Handle FIFO underflow IRQs internally
  2016-12-14 11:48     ` Laurent Pinchart
@ 2016-12-14 13:13       ` Tomi Valkeinen
  2016-12-15  9:02       ` Tomi Valkeinen
  1 sibling, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-14 13:13 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 2610 bytes --]

On 14/12/16 13:48, Laurent Pinchart wrote:
> Hi Tomi,
> 
> On Wednesday 14 Dec 2016 12:22:29 Tomi Valkeinen wrote:
>> On 14/12/16 02:27, Laurent Pinchart wrote:
>>> As the FIFO underflow IRQ handler just prints an error message to the
>>> kernel log, simplify the code by not registering one IRQ handler per
>>> plane but print the messages directly from the main IRQ handler.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>>> ---
>>>
>>> +static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
>>> +				    u32 irqstatus)
>>> +{
>>> +	static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
>>> +				      DEFAULT_RATELIMIT_BURST);
>>> +	static const struct {
>>> +		const char *name;
>>> +		u32 mask;
>>> +	} sources[] = {
>>> +		{ "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW },
>>> +		{ "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW },
>>> +		{ "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW },
>>> +		{ "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW },
>>> +	};
>>> +
>>> +	const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW
>>> +		       | DISPC_IRQ_VID1_FIFO_UNDERFLOW
>>> +		       | DISPC_IRQ_VID2_FIFO_UNDERFLOW
>>> +		       | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
>>> +	unsigned int i;
>>> +
>>> +	spin_lock(&list_lock);
>>> +	irqstatus &= priv->irq_mask & mask;
>>> +	spin_unlock(&list_lock);
>>> +
>>> +	if (!irqstatus)
>>> +		return;
>>
>> This is called every time we get any DSS interrupt, so I think it would
>> be good to have a fast-path here without the lock: irqstatus & mask.
>>
>> Or maybe store the enabled underflow irq bits separately from irq_mask,
>> as the underflow bits are never changed after the initial setup, and
>> then there's no need for locking.
> 
> I'd prefer going for the former, but I'm a bit concerned that an IRQ bit 
> defined as FIFO overflow on one platform could be defined as something else on 
> another platform and be mistaken.

I meant that you could first check irqstatus & mask, and exit if 0.
After that you could do the above spinlock, and the check against
priv->irq_mask & mask.

So yes, it's not perfect either, and in the worst case could mean still
doing the spinlock at every irq... But, if I'm not mistaken, the current
HW versions do not have overlapping irq bits.

> Given that we already take the same lock in the IRQ handler to call the wait 
> handlers, do you think this is really an issue ?

I don't think it's really an issue. But it's nice to optimize irq
handlers, especially as this is a hard-irq.

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 11/22] drm: omapdrm: Check the CRTC software state at enable/disable time
  2016-12-14  0:27 ` [PATCH v4 11/22] drm: omapdrm: Check the CRTC software state at enable/disable time Laurent Pinchart
@ 2016-12-14 14:54   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-14 14:54 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 2898 bytes --]



On 14/12/16 02:27, Laurent Pinchart wrote:
> The omapdrm DSS manager enable/disable operations check the DSS manager
> state to avoid double enabling/disabling. Check the CRTC software state
> instead to decrease the dependency of the DRM layer to the DSS layer.
> The dispc_mgr_is_enabled() function then be turned into a static
> function, but needs to be moved up in its compilation unit to avoid a
> forward declaration.
> 
> Add a WARN_ON to catch double enable or disable that should be prevented
> by the DRM core and would be a clear sign of a bug. The warning should
> eventually be removed.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v3:
> 
> - Replace the hardware state check with a software state check in
>   omapdrm instead of moving it to omapdss.
> - Added a WARN_ON to catch impossible situations that would be a sign of
>   a clear bug
> ---
>  drivers/gpu/drm/omapdrm/dss/dispc.c   | 27 +++++++++++++--------------
>  drivers/gpu/drm/omapdrm/dss/omapdss.h |  1 -
>  drivers/gpu/drm/omapdrm/omap_crtc.c   |  6 +++---
>  3 files changed, 16 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
> index c839f6456db2..5554b72cf56a 100644
> --- a/drivers/gpu/drm/omapdrm/dss/dispc.c
> +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
> @@ -620,6 +620,19 @@ u32 dispc_wb_get_framedone_irq(void)
>  	return DISPC_IRQ_FRAMEDONEWB;
>  }
>  
> +void dispc_mgr_enable(enum omap_channel channel, bool enable)
> +{
> +	mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
> +	/* flush posted write */
> +	mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
> +}
> +EXPORT_SYMBOL(dispc_mgr_enable);
> +
> +static bool dispc_mgr_is_enabled(enum omap_channel channel)
> +{
> +	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
> +}
> +
>  bool dispc_mgr_go_busy(enum omap_channel channel)
>  {
>  	return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
> @@ -2901,20 +2914,6 @@ enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channe
>  }
>  EXPORT_SYMBOL(dispc_mgr_get_supported_outputs);
>  
> -void dispc_mgr_enable(enum omap_channel channel, bool enable)
> -{
> -	mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
> -	/* flush posted write */
> -	mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
> -}
> -EXPORT_SYMBOL(dispc_mgr_enable);
> -
> -bool dispc_mgr_is_enabled(enum omap_channel channel)
> -{
> -	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
> -}
> -EXPORT_SYMBOL(dispc_mgr_is_enabled);
> -

dispc_mgr_is_enabled() is only used in a WARN, so we could even drop the
function, and then no moving is needed. But I'd rather leave that WARN
at least for now. It's quite good at catching bad SW. So:

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 06/22] drm: omapdrm: Handle FIFO underflow IRQs internally
  2016-12-14 11:48     ` Laurent Pinchart
  2016-12-14 13:13       ` Tomi Valkeinen
@ 2016-12-15  9:02       ` Tomi Valkeinen
  1 sibling, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-15  9:02 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 2241 bytes --]

On 14/12/16 13:48, Laurent Pinchart wrote:
> Hi Tomi,
> 
> On Wednesday 14 Dec 2016 12:22:29 Tomi Valkeinen wrote:
>> On 14/12/16 02:27, Laurent Pinchart wrote:
>>> As the FIFO underflow IRQ handler just prints an error message to the
>>> kernel log, simplify the code by not registering one IRQ handler per
>>> plane but print the messages directly from the main IRQ handler.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>>> ---
>>>
>>> +static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
>>> +				    u32 irqstatus)
>>> +{
>>> +	static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
>>> +				      DEFAULT_RATELIMIT_BURST);
>>> +	static const struct {
>>> +		const char *name;
>>> +		u32 mask;
>>> +	} sources[] = {
>>> +		{ "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW },
>>> +		{ "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW },
>>> +		{ "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW },
>>> +		{ "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW },
>>> +	};
>>> +
>>> +	const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW
>>> +		       | DISPC_IRQ_VID1_FIFO_UNDERFLOW
>>> +		       | DISPC_IRQ_VID2_FIFO_UNDERFLOW
>>> +		       | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
>>> +	unsigned int i;
>>> +
>>> +	spin_lock(&list_lock);
>>> +	irqstatus &= priv->irq_mask & mask;
>>> +	spin_unlock(&list_lock);
>>> +
>>> +	if (!irqstatus)
>>> +		return;
>>
>> This is called every time we get any DSS interrupt, so I think it would
>> be good to have a fast-path here without the lock: irqstatus & mask.
>>
>> Or maybe store the enabled underflow irq bits separately from irq_mask,
>> as the underflow bits are never changed after the initial setup, and
>> then there's no need for locking.
> 
> I'd prefer going for the former, but I'm a bit concerned that an IRQ bit 
> defined as FIFO overflow on one platform could be defined as something else on 
> another platform and be mistaken.
> 
> Given that we already take the same lock in the IRQ handler to call the wait 
> handlers, do you think this is really an issue ?

Yep, I think it's fine for the time being.

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 12/22] drm: omapdrm: Prevent processing the same event multiple times
  2016-12-14  0:27 ` [PATCH v4 12/22] drm: omapdrm: Prevent processing the same event multiple times Laurent Pinchart
@ 2016-12-15 12:20   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-15 12:20 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 1085 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> The vblank interrupt is disabled after one occurrence, preventing the
> atomic update event from being processed twice. However, this also
> prevents the software frame counter from being updated correctly that
> would require vblank interrupts to be kept enabled while the CRTC is
> active.
> 
> In preparation for vblank interrupt fixes, make sure that the atomic
> update event will be processed once only when the vblank interrupt will
> be kept enabled.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v3:
> 
> - Don't release and reacquire the spinlock for just one return
> - Remove unneeded (and unbalanced) drm_crtc_vblank_get()
> - Store the event in the atomic flush handler to avoid race condition
> - Use spin_lock_irq instead of spin_lock_irsave in flush handler
> ---
>  drivers/gpu/drm/omapdrm/omap_crtc.c | 23 +++++++++++++++--------
>  1 file changed, 15 insertions(+), 8 deletions(-)

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active
  2016-12-14  0:27 ` [PATCH v4 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active Laurent Pinchart
@ 2016-12-15 12:52   ` Tomi Valkeinen
  2016-12-15 14:51     ` Laurent Pinchart
  2016-12-18  2:12   ` [PATCH v4.1 " Laurent Pinchart
  1 sibling, 1 reply; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-15 12:52 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 4163 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> Instead of going through a complicated private IRQ registration
> mechanism, handle the vblank interrupt activation with the standard
> drm_crtc_vblank_get() and drm_crtc_vblank_put() mechanism. This will let
> the DRM core keep the vblank interrupt enabled as long as needed to
> update the frame counter.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/omapdrm/omap_crtc.c | 38 ++++++++++++++-----------------------
>  drivers/gpu/drm/omapdrm/omap_drv.h  |  1 +
>  drivers/gpu/drm/omapdrm/omap_irq.c  |  4 +++-
>  3 files changed, 18 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
> index 827ac46a6d5e..1f5372042706 100644
> --- a/drivers/gpu/drm/omapdrm/omap_crtc.c
> +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
> @@ -36,8 +36,6 @@ struct omap_crtc {
>  
>  	struct videomode vm;
>  
> -	struct omap_drm_irq vblank_irq;
> -
>  	bool ignore_digit_sync_lost;
>  
>  	bool enabled;
> @@ -304,25 +302,24 @@ void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus)
>  	DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus);
>  }
>  
> -static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
> +void omap_crtc_vblank_irq(struct drm_crtc *crtc)
>  {
> -	struct omap_crtc *omap_crtc =
> -			container_of(irq, struct omap_crtc, vblank_irq);
> -	struct drm_device *dev = omap_crtc->base.dev;
> -	struct drm_crtc *crtc = &omap_crtc->base;
> +	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
> +	bool pending;
>  
>  	if (dispc_mgr_go_busy(omap_crtc->channel))
>  		return;
>  
>  	DBG("%s: apply done", omap_crtc->name);
>  
> -	__omap_irq_unregister(dev, &omap_crtc->vblank_irq);
> -
>  	spin_lock(&crtc->dev->event_lock);
> -	WARN_ON(!omap_crtc->pending);
> +	pending = omap_crtc->pending;
>  	omap_crtc->pending = false;
>  	spin_unlock(&crtc->dev->event_lock);
>  
> +	if (pending)
> +		drm_crtc_vblank_put(crtc);
> +

I think there's a race.

- irq: we get vblank irq
- irq: GO is not set, so dispc_mgr_go_busy() check doesn't trigger
- flush: we set GO
- flush: we lock event_lock and set the pending & event, and unlock
- irq: irq handler continues, sees pending and event, and thinks that
the config has been taken into use, but in reality GO bit is set and
it'll happen only on next vblank.


>  	/* wake up userspace */
>  	omap_crtc_complete_page_flip(&omap_crtc->base);
>  
> @@ -340,8 +337,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
>  
>  	DBG("%s", omap_crtc->name);
>  
> -	WARN_ON(omap_crtc->vblank_irq.registered);
> -
>  	drm_crtc_cleanup(crtc);
>  
>  	kfree(omap_crtc);
> @@ -353,14 +348,13 @@ static void omap_crtc_enable(struct drm_crtc *crtc)
>  
>  	DBG("%s", omap_crtc->name);
>  
> +	drm_crtc_vblank_on(crtc);
> +	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
> +
>  	spin_lock_irq(&crtc->dev->event_lock);
>  	WARN_ON(omap_crtc->pending);
>  	omap_crtc->pending = true;
>  	spin_unlock_irq(&crtc->dev->event_lock);
> -
> -	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
> -
> -	drm_crtc_vblank_on(crtc);
>  }
>  
>  static void omap_crtc_disable(struct drm_crtc *crtc)
> @@ -414,8 +408,6 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
>  {
>  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
>  
> -	WARN_ON(omap_crtc->vblank_irq.registered);
> -
>  	if (crtc->state->color_mgmt_changed) {
>  		struct drm_color_lut *lut = NULL;
>  		uint length = 0;
> @@ -441,6 +433,10 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
>  
>  	DBG("%s: GO", omap_crtc->name);
>  
> +	dispc_mgr_go(omap_crtc->channel);
> +
> +	WARN_ON(drm_crtc_vblank_get(crtc) != 0);

I don't like this style very much. I think WARN()s should be without
side effects.

Also, WARN only gives benefit when we don't know what the call stack is.
Afaik, there's only one way omap_crtc_atomic_flush can be called, so
it's just extra spam and dev_err or dev_warn should be enough.

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 15/22] drm: omapdrm: Don't expose the omap_irq_(un)register() functions
  2016-12-14  0:27 ` [PATCH v4 15/22] drm: omapdrm: Don't expose the omap_irq_(un)register() functions Laurent Pinchart
@ 2016-12-15 12:56   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-15 12:56 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 698 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> The IRQ registration functions are not used outside of their compilation
> unit, make them static. As the __omap_irq_(un)register() functions are
> only called by their omap_irq_(un)register() counterparts, merge them
> together.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v1:
> 
> - Split the omap_drm_irq irqstatus parameter removal change out
> ---
>  drivers/gpu/drm/omapdrm/omap_drv.h |  4 ----
>  drivers/gpu/drm/omapdrm/omap_irq.c | 23 +++++------------------
>  2 files changed, 5 insertions(+), 22 deletions(-)

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 16/22] drm: omapdrm: Remove unused parameter from omap_drm_irq handler
  2016-12-14  0:27 ` [PATCH v4 16/22] drm: omapdrm: Remove unused parameter from omap_drm_irq handler Laurent Pinchart
@ 2016-12-15 12:57   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-15 12:57 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 493 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> The only omap_drm_irq handler doesn't use the irqstatus parameter passed
> to the function. Remove it.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v1:
> 
> - New patch
> ---
>  drivers/gpu/drm/omapdrm/omap_drv.h | 2 +-
>  drivers/gpu/drm/omapdrm/omap_irq.c | 4 ++--
>  2 files changed, 3 insertions(+), 3 deletions(-)

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 17/22] drm: omapdrm: Don't call DISPC power handling in IRQ wait functions
  2016-12-14  0:27 ` [PATCH v4 17/22] drm: omapdrm: Don't call DISPC power handling in IRQ wait functions Laurent Pinchart
@ 2016-12-15 13:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-15 13:00 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 469 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> The IRQ wait functions are called from the DSS enable and disable
> operations only, where the DISPC is guaranteed to be enabled. There's no
> need for manual DISPC power management there.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/omapdrm/omap_irq.c | 4 ----
>  1 file changed, 4 deletions(-)

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 21/22] drm: omapdrm: Use sizeof(*var) instead of sizeof(type) for structures
  2016-12-14  0:27 ` [PATCH v4 21/22] drm: omapdrm: Use sizeof(*var) instead of sizeof(type) for structures Laurent Pinchart
@ 2016-12-15 13:02   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-15 13:02 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 724 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> By linking the sizeof to a variable type the code will be less prone to
> bugs due to future type changes of variables.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 2 +-
>  drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c | 3 +--
>  drivers/gpu/drm/omapdrm/omap_connector.c        | 4 ++--
>  drivers/gpu/drm/omapdrm/omap_dmm_tiler.c        | 4 ++--
>  drivers/gpu/drm/omapdrm/omap_encoder.c          | 2 +-
>  5 files changed, 7 insertions(+), 8 deletions(-)

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active
  2016-12-15 12:52   ` Tomi Valkeinen
@ 2016-12-15 14:51     ` Laurent Pinchart
  2016-12-15 14:56       ` Tomi Valkeinen
  0 siblings, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-15 14:51 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: dri-devel

Hi Tomi,

On Thursday 15 Dec 2016 14:52:47 Tomi Valkeinen wrote:
> On 14/12/16 02:27, Laurent Pinchart wrote:
> > Instead of going through a complicated private IRQ registration
> > mechanism, handle the vblank interrupt activation with the standard
> > drm_crtc_vblank_get() and drm_crtc_vblank_put() mechanism. This will let
> > the DRM core keep the vblank interrupt enabled as long as needed to
> > update the frame counter.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/omapdrm/omap_crtc.c | 38 ++++++++++++--------------------
> >  drivers/gpu/drm/omapdrm/omap_drv.h  |  1 +
> >  drivers/gpu/drm/omapdrm/omap_irq.c  |  4 +++-
> >  3 files changed, 18 insertions(+), 25 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c
> > b/drivers/gpu/drm/omapdrm/omap_crtc.c index 827ac46a6d5e..1f5372042706
> > 100644
> > --- a/drivers/gpu/drm/omapdrm/omap_crtc.c
> > +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
> > @@ -36,8 +36,6 @@ struct omap_crtc {
> > 
> >  	struct videomode vm;
> > 
> > -	struct omap_drm_irq vblank_irq;
> > -
> >  	bool ignore_digit_sync_lost;
> >  	bool enabled;
> > 
> > @@ -304,25 +302,24 @@ void omap_crtc_error_irq(struct drm_crtc *crtc,
> > uint32_t irqstatus)
> >  	DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, 
irqstatus);
> >  }
> > 
> > -static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t
> > irqstatus)
> > +void omap_crtc_vblank_irq(struct drm_crtc *crtc)
> >  {
> > -	struct omap_crtc *omap_crtc =
> > -			container_of(irq, struct omap_crtc, vblank_irq);
> > -	struct drm_device *dev = omap_crtc->base.dev;
> > -	struct drm_crtc *crtc = &omap_crtc->base;
> > +	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
> > +	bool pending;
> > 
> >  	if (dispc_mgr_go_busy(omap_crtc->channel))
> >  		return;
> >  	
> >  	DBG("%s: apply done", omap_crtc->name);
> > 
> > -	__omap_irq_unregister(dev, &omap_crtc->vblank_irq);
> > -
> >  	spin_lock(&crtc->dev->event_lock);
> > 
> > -	WARN_ON(!omap_crtc->pending);
> > +	pending = omap_crtc->pending;
> > 
> >  	omap_crtc->pending = false;
> >  	spin_unlock(&crtc->dev->event_lock);
> > 
> > +	if (pending)
> > +		drm_crtc_vblank_put(crtc);
> > +
> 
> I think there's a race.
> 
> - irq: we get vblank irq
> - irq: GO is not set, so dispc_mgr_go_busy() check doesn't trigger
> - flush: we set GO
> - flush: we lock event_lock and set the pending & event, and unlock
> - irq: irq handler continues, sees pending and event, and thinks that
> the config has been taken into use, but in reality GO bit is set and
> it'll happen only on next vblank.

I think you're right. I'll try to fix it.

> >  	/* wake up userspace */
> >  	omap_crtc_complete_page_flip(&omap_crtc->base);
> > 
> > @@ -340,8 +337,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
> > 
> >  	DBG("%s", omap_crtc->name);
> > 
> > -	WARN_ON(omap_crtc->vblank_irq.registered);
> > -
> >  	drm_crtc_cleanup(crtc);
> >  	
> >  	kfree(omap_crtc);
> > @@ -353,14 +348,13 @@ static void omap_crtc_enable(struct drm_crtc *crtc)
> > 
> >  	DBG("%s", omap_crtc->name);
> > 
> > +	drm_crtc_vblank_on(crtc);
> > +	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
> > +
> >  	spin_lock_irq(&crtc->dev->event_lock);
> >  	WARN_ON(omap_crtc->pending);
> >  	omap_crtc->pending = true;
> >  	spin_unlock_irq(&crtc->dev->event_lock);
> > -
> > -	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
> > -
> > -	drm_crtc_vblank_on(crtc);
> >  }
> >  
> >  static void omap_crtc_disable(struct drm_crtc *crtc)
> > @@ -414,8 +408,6 @@ static void omap_crtc_atomic_flush(struct drm_crtc
> > *crtc,
> >  {
> >  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
> > 
> > -	WARN_ON(omap_crtc->vblank_irq.registered);
> > -
> >  	if (crtc->state->color_mgmt_changed) {
> >  		struct drm_color_lut *lut = NULL;
> >  		uint length = 0;
> > @@ -441,6 +433,10 @@ static void omap_crtc_atomic_flush(struct drm_crtc
> > *crtc,
> > 
> >  	DBG("%s: GO", omap_crtc->name);
> > 
> > +	dispc_mgr_go(omap_crtc->channel);
> > +
> > +	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
> 
> I don't like this style very much. I think WARN()s should be without
> side effects.
> 
> Also, WARN only gives benefit when we don't know what the call stack is.
> Afaik, there's only one way omap_crtc_atomic_flush can be called, so
> it's just extra spam and dev_err or dev_warn should be enough.

I've used it because the equivalent statements testing omap_crtc-
>vblank_irq.registered used WARN_ON() too. WARN_ON() is also a bit more vocal, 
it really gets the point across. As the function really should not return an 
error unless in case of a driver bug, I don't think it will generate any spam. 
I don't care too much though, I can replace it with a dev_err() if you insist.

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active
  2016-12-15 14:51     ` Laurent Pinchart
@ 2016-12-15 14:56       ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-15 14:56 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 1177 bytes --]

On 15/12/16 16:51, Laurent Pinchart wrote:

>>> +	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
>>
>> I don't like this style very much. I think WARN()s should be without
>> side effects.
>>
>> Also, WARN only gives benefit when we don't know what the call stack is.
>> Afaik, there's only one way omap_crtc_atomic_flush can be called, so
>> it's just extra spam and dev_err or dev_warn should be enough.
> 
> I've used it because the equivalent statements testing omap_crtc-
>> vblank_irq.registered used WARN_ON() too. WARN_ON() is also a bit more vocal, 
> it really gets the point across. As the function really should not return an 
> error unless in case of a driver bug, I don't think it will generate any spam. 
> I don't care too much though, I can replace it with a dev_err() if you insist.

I don't mind using WARN_ON() that much. But that's the comment I've
received a few times, so I shared it =).

What I do care is the side effect inside WARN_ON. At least for me it's
quite easy to miss that it's actually having a side effect, as I expect
WARN_ON() to be just a check, like assert(). So when reading the code, I
skip the WARN_ONs.

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 19/22] drm: omapdrm: Simplify IRQ wait implementation
  2016-12-14  0:27 ` [PATCH v4 19/22] drm: omapdrm: Simplify IRQ wait implementation Laurent Pinchart
@ 2016-12-16 12:24   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-16 12:24 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 6917 bytes --]



On 14/12/16 02:27, Laurent Pinchart wrote:
> Now that the IRQ list is used for IRQ wait only we can merge
> omap_drm_irq and omap_irq_wait and simplify the implementation.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/omapdrm/omap_drv.h | 17 +------
>  drivers/gpu/drm/omapdrm/omap_irq.c | 94 ++++++++++++++------------------------
>  2 files changed, 37 insertions(+), 74 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
> index dad7d6161563..8ef7e8963bd9 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.h
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.h
> @@ -48,19 +48,6 @@ struct omap_drm_window {
>  	uint32_t src_w, src_h;
>  };
>  
> -/* For transiently registering for different DSS irqs that various parts
> - * of the KMS code need during setup/configuration.  We these are not
> - * necessarily the same as what drm_vblank_get/put() are requesting, and
> - * the hysteresis in drm_vblank_put() is not necessarily desirable for
> - * internal housekeeping related irq usage.
> - */
> -struct omap_drm_irq {
> -	struct list_head node;
> -	uint32_t irqmask;
> -	bool registered;
> -	void (*irq)(struct omap_drm_irq *irq);
> -};
> -
>  /* For KMS code that needs to wait for a certain # of IRQs:
>   */
>  struct omap_irq_wait;
> @@ -101,8 +88,8 @@ struct omap_drm_private {
>  	struct drm_property *zorder_prop;
>  
>  	/* irq handling: */
> -	struct list_head irq_list;    /* list of omap_drm_irq */
> -	uint32_t irq_mask;		/* enabled irqs in addition to irq_list */
> +	struct list_head wait_list;     /* list of omap_irq_wait */
> +	uint32_t irq_mask;		/* enabled irqs in addition to wait_list */
>  
>  	/* atomic commit */
>  	struct {
> diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
> index 1982759a1c27..f9510c13e1a2 100644
> --- a/drivers/gpu/drm/omapdrm/omap_irq.c
> +++ b/drivers/gpu/drm/omapdrm/omap_irq.c
> @@ -21,17 +21,23 @@
>  
>  static DEFINE_SPINLOCK(list_lock);
>  
> +struct omap_irq_wait {
> +	struct list_head node;
> +	uint32_t irqmask;
> +	int count;
> +};
> +
>  /* call with list_lock and dispc runtime held */
>  static void omap_irq_update(struct drm_device *dev)
>  {
>  	struct omap_drm_private *priv = dev->dev_private;
> -	struct omap_drm_irq *irq;
> +	struct omap_irq_wait *wait;
>  	uint32_t irqmask = priv->irq_mask;
>  
>  	assert_spin_locked(&list_lock);
>  
> -	list_for_each_entry(irq, &priv->irq_list, node)
> -		irqmask |= irq->irqmask;
> +	list_for_each_entry(wait, &priv->wait_list, node)
> +		irqmask |= wait->irqmask;
>  
>  	DBG("irqmask=%08x", irqmask);
>  
> @@ -39,61 +45,29 @@ static void omap_irq_update(struct drm_device *dev)
>  	dispc_read_irqenable();        /* flush posted write */
>  }
>  
> -static void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
> -{
> -	struct omap_drm_private *priv = dev->dev_private;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&list_lock, flags);
> -
> -	if (!WARN_ON(irq->registered)) {
> -		irq->registered = true;
> -		list_add(&irq->node, &priv->irq_list);
> -		omap_irq_update(dev);
> -	}
> -
> -	spin_unlock_irqrestore(&list_lock, flags);
> -}
> -
> -static void omap_irq_unregister(struct drm_device *dev,
> -				struct omap_drm_irq *irq)
> -{
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&list_lock, flags);
> -
> -	if (!WARN_ON(!irq->registered)) {
> -		irq->registered = false;
> -		list_del(&irq->node);
> -		omap_irq_update(dev);
> -	}
> -
> -	spin_unlock_irqrestore(&list_lock, flags);
> -}
> -
> -struct omap_irq_wait {
> -	struct omap_drm_irq irq;
> -	int count;
> -};
> -
>  static DECLARE_WAIT_QUEUE_HEAD(wait_event);
>  
> -static void wait_irq(struct omap_drm_irq *irq)
> +static void omap_irq_wait_irq(struct omap_irq_wait *wait)

I think omap_irq_wait_irq_handler() or something like that would be a
better name. At least my thought based on the function name is that the
function waits.

>  {
> -	struct omap_irq_wait *wait =
> -			container_of(irq, struct omap_irq_wait, irq);
>  	wait->count--;
> -	wake_up_all(&wait_event);
> +	wake_up(&wait_event);
>  }
>  
>  struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
>  		uint32_t irqmask, int count)
>  {
> +	struct omap_drm_private *priv = dev->dev_private;
>  	struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);

A separate improvement, but I think we could just drop the
kzalloc/kfree, and use a local omap_irq_wait variable, passed to these
funcs.

> -	wait->irq.irq = wait_irq;
> -	wait->irq.irqmask = irqmask;
> +	unsigned long flags;
> +
> +	wait->irqmask = irqmask;
>  	wait->count = count;
> -	omap_irq_register(dev, &wait->irq);
> +
> +	spin_lock_irqsave(&list_lock, flags);
> +	list_add(&wait->node, &priv->wait_list);
> +	omap_irq_update(dev);
> +	spin_unlock_irqrestore(&list_lock, flags);
> +
>  	return wait;
>  }
>  
> @@ -101,11 +75,16 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
>  		unsigned long timeout)
>  {
>  	int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout);
> -	omap_irq_unregister(dev, &wait->irq);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&list_lock, flags);
> +	list_del(&wait->node);
> +	omap_irq_update(dev);
> +	spin_unlock_irqrestore(&list_lock, flags);
> +
>  	kfree(wait);
> -	if (ret == 0)
> -		return -1;
> -	return 0;
> +
> +	return ret == 0 ? -1 : 0;
>  }
>  
>  /**
> @@ -213,7 +192,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
>  {
>  	struct drm_device *dev = (struct drm_device *) arg;
>  	struct omap_drm_private *priv = dev->dev_private;
> -	struct omap_drm_irq *handler, *n;
> +	struct omap_irq_wait *wait, *n;
>  	unsigned long flags;
>  	unsigned int id;
>  	u32 irqstatus;
> @@ -241,12 +220,9 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
>  	omap_irq_fifo_underflow(priv, irqstatus);
>  
>  	spin_lock_irqsave(&list_lock, flags);
> -	list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
> -		if (handler->irqmask & irqstatus) {
> -			spin_unlock_irqrestore(&list_lock, flags);
> -			handler->irq(handler);
> -			spin_lock_irqsave(&list_lock, flags);
> -		}
> +	list_for_each_entry_safe(wait, n, &priv->wait_list, node) {
> +		if (wait->irqmask & irqstatus)
> +			omap_irq_wait_irq(wait);
>  	}
>  	spin_unlock_irqrestore(&list_lock, flags);
>  
> @@ -275,7 +251,7 @@ int omap_drm_irq_install(struct drm_device *dev)
>  	unsigned int i;
>  	int ret;
>  
> -	INIT_LIST_HEAD(&priv->irq_list);
> +	INIT_LIST_HEAD(&priv->wait_list);
>  
>  	priv->irq_mask = DISPC_IRQ_OCP_ERR;
>  
> 

With the function rename change:

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 20/22] drm: omapdrm: Remove global variables
  2016-12-14  0:27 ` [PATCH v4 20/22] drm: omapdrm: Remove global variables Laurent Pinchart
@ 2016-12-16 12:31   ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-16 12:31 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 1760 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> Move the list of pending IRQ wait instances to the omap_drm_private
> structure and the wait queue head to the IRQ wait structure.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/omapdrm/omap_drv.h |  3 ++-
>  drivers/gpu/drm/omapdrm/omap_irq.c | 42 ++++++++++++++++++++------------------
>  2 files changed, 24 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
> index 8ef7e8963bd9..b20377efd01b 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.h
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.h
> @@ -88,7 +88,8 @@ struct omap_drm_private {
>  	struct drm_property *zorder_prop;
>  
>  	/* irq handling: */
> -	struct list_head wait_list;     /* list of omap_irq_wait */
> +	spinlock_t wait_lock;		/* protects the wait_list */
> +	struct list_head wait_list;	/* list of omap_irq_wait */
>  	uint32_t irq_mask;		/* enabled irqs in addition to wait_list */
>  
>  	/* atomic commit */
> diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
> index f9510c13e1a2..7555b62f6c53 100644
> --- a/drivers/gpu/drm/omapdrm/omap_irq.c
> +++ b/drivers/gpu/drm/omapdrm/omap_irq.c
> @@ -19,22 +19,21 @@
>  
>  #include "omap_drv.h"
>  
> -static DEFINE_SPINLOCK(list_lock);
> -
>  struct omap_irq_wait {
>  	struct list_head node;
> +	wait_queue_head_t wq;
>  	uint32_t irqmask;
>  	int count;
>  };

The wait_queue_head_t + count combination looks suspiciously like
completion. But as there's no wait_for_completion_count(), I guess the
current implementation is better.

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 22/22] drm: omapdrm: Perform initialization/cleanup at probe/remove time
  2016-12-14  0:27 ` [PATCH v4 22/22] drm: omapdrm: Perform initialization/cleanup at probe/remove time Laurent Pinchart
@ 2016-12-16 12:44   ` Tomi Valkeinen
  2016-12-16 13:54     ` Laurent Pinchart
  2016-12-19  9:15   ` [PATCH v4.1 " Laurent Pinchart
  1 sibling, 1 reply; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-16 12:44 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 8532 bytes --]

On 14/12/16 02:27, Laurent Pinchart wrote:
> The drm driver .load() operation is prone to race conditions as it
> initializes the driver after registering the device nodes. Its usage is
> deprecated, inline it in the probe function and call drm_dev_alloc() and
> drm_dev_register() explicitly.
> 
> For consistency inline the .unload() handler in the remove function as
> well.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v1:
> 
> - Call drm_kms_helper_poll_fini() before omap_fbdev_free() in the remove
>   handler.
> - Keep storing drm_device in the platform device private data.
> ---
>  drivers/gpu/drm/omapdrm/omap_connector.c |   2 -
>  drivers/gpu/drm/omapdrm/omap_drv.c       | 212 ++++++++++++++++---------------
>  2 files changed, 107 insertions(+), 107 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
> index 691cffebb76e..f90e2d22c5ec 100644
> --- a/drivers/gpu/drm/omapdrm/omap_connector.c
> +++ b/drivers/gpu/drm/omapdrm/omap_connector.c
> @@ -240,8 +240,6 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
>  	connector->interlace_allowed = 1;
>  	connector->doublescan_allowed = 0;
>  
> -	drm_connector_register(connector);
> -
>  	return connector;
>  
>  fail:
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> index 0a2d461d62cf..a3b37823b271 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -493,11 +493,6 @@ static int omap_modeset_init(struct drm_device *dev)
>  	return 0;
>  }
>  
> -static void omap_modeset_free(struct drm_device *dev)
> -{
> -	drm_mode_config_cleanup(dev);
> -}
> -
>  /*
>   * drm ioctl funcs
>   */
> @@ -633,95 +628,6 @@ static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] =
>   * drm driver funcs
>   */
>  
> -/**
> - * load - setup chip and create an initial config
> - * @dev: DRM device
> - * @flags: startup flags
> - *
> - * The driver load routine has to do several things:
> - *   - initialize the memory manager
> - *   - allocate initial config memory
> - *   - setup the DRM framebuffer with the allocated memory
> - */
> -static int dev_load(struct drm_device *dev, unsigned long flags)
> -{
> -	struct omap_drm_platform_data *pdata = dev->dev->platform_data;
> -	struct omap_drm_private *priv;
> -	unsigned int i;
> -	int ret;
> -
> -	DBG("load: dev=%p", dev);
> -
> -	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> -	if (!priv)
> -		return -ENOMEM;
> -
> -	priv->omaprev = pdata->omaprev;
> -
> -	dev->dev_private = priv;
> -
> -	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
> -	init_waitqueue_head(&priv->commit.wait);
> -	spin_lock_init(&priv->commit.lock);
> -
> -	spin_lock_init(&priv->list_lock);
> -	INIT_LIST_HEAD(&priv->obj_list);
> -
> -	omap_gem_init(dev);
> -
> -	ret = omap_modeset_init(dev);
> -	if (ret) {
> -		dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
> -		dev->dev_private = NULL;
> -		kfree(priv);
> -		return ret;
> -	}
> -
> -	/* Initialize vblank handling, start with all CRTCs disabled. */
> -	ret = drm_vblank_init(dev, priv->num_crtcs);
> -	if (ret)
> -		dev_warn(dev->dev, "could not init vblank\n");
> -
> -	for (i = 0; i < priv->num_crtcs; i++)
> -		drm_crtc_vblank_off(priv->crtcs[i]);
> -
> -	priv->fbdev = omap_fbdev_init(dev);
> -
> -	/* store off drm_device for use in pm ops */
> -	dev_set_drvdata(dev->dev, dev);
> -
> -	drm_kms_helper_poll_init(dev);
> -
> -	return 0;
> -}
> -
> -static int dev_unload(struct drm_device *dev)
> -{
> -	struct omap_drm_private *priv = dev->dev_private;
> -
> -	DBG("unload: dev=%p", dev);
> -
> -	drm_kms_helper_poll_fini(dev);
> -
> -	if (priv->fbdev)
> -		omap_fbdev_free(dev);
> -
> -	omap_modeset_free(dev);
> -	omap_gem_deinit(dev);
> -
> -	destroy_workqueue(priv->wq);
> -
> -	drm_vblank_cleanup(dev);
> -	omap_drm_irq_uninstall(dev);
> -
> -	kfree(dev->dev_private);
> -	dev->dev_private = NULL;
> -
> -	dev_set_drvdata(dev->dev, NULL);
> -
> -	return 0;
> -}
> -
>  static int dev_open(struct drm_device *dev, struct drm_file *file)
>  {
>  	file->driver_priv = NULL;
> @@ -806,8 +712,6 @@ static const struct file_operations omapdriver_fops = {
>  static struct drm_driver omap_drm_driver = {
>  	.driver_features = DRIVER_MODESET | DRIVER_GEM  | DRIVER_PRIME |
>  		DRIVER_ATOMIC,
> -	.load = dev_load,
> -	.unload = dev_unload,
>  	.open = dev_open,
>  	.lastclose = dev_lastclose,
>  	.get_vblank_counter = drm_vblank_no_hw_counter,
> @@ -837,30 +741,128 @@ static struct drm_driver omap_drm_driver = {
>  	.patchlevel = DRIVER_PATCHLEVEL,
>  };
>  
> -static int pdev_probe(struct platform_device *device)
> +static int pdev_probe(struct platform_device *pdev)
>  {
> -	int r;
> +	struct omap_drm_platform_data *pdata = pdev->dev.platform_data;
> +	struct omap_drm_private *priv;
> +	struct drm_device *ddev;
> +	unsigned int i;
> +	int ret;
> +
> +	DBG("%s", pdev->name);
>  
>  	if (omapdss_is_initialized() == false)
>  		return -EPROBE_DEFER;
>  
>  	omap_crtc_pre_init();
>  
> -	r = omap_connect_dssdevs();
> -	if (r) {
> +	ret = omap_connect_dssdevs();
> +	if (ret) {
>  		omap_crtc_pre_uninit();
> -		return r;
> +		goto err_crtc_uninit;

This calls omap_crtc_pre_uninit here and in the err handler.

> +	}
> +
> +	/* Allocate and initialize the driver private structure. */
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		ret = -ENOMEM;
> +		goto err_disconnect_dssdevs;
> +	}
> +
> +	priv->omaprev = pdata->omaprev;
> +	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
> +
> +	init_waitqueue_head(&priv->commit.wait);
> +	spin_lock_init(&priv->commit.lock);
> +	spin_lock_init(&priv->list_lock);
> +	INIT_LIST_HEAD(&priv->obj_list);
> +
> +	/* Allocate and initialize the DRM device. */
> +	ddev = drm_dev_alloc(&omap_drm_driver, &pdev->dev);
> +	if (IS_ERR(ddev)) {
> +		ret = PTR_ERR(ddev);
> +		goto err_free_priv;
> +	}
> +
> +	ddev->dev_private = priv;
> +	platform_set_drvdata(pdev, ddev);
> +
> +	omap_gem_init(ddev);
> +
> +	ret = omap_modeset_init(ddev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "omap_modeset_init failed: ret=%d\n", ret);
> +		goto err_free_drm_dev;
> +	}
> +
> +	/* Initialize vblank handling, start with all CRTCs disabled. */
> +	ret = drm_vblank_init(ddev, priv->num_crtcs);
> +	if (ret) {
> +		dev_err(&pdev->dev, "could not init vblank\n");
> +		goto err_cleanup_modeset;
>  	}
>  
> -	DBG("%s", device->name);
> -	return drm_platform_init(&omap_drm_driver, device);
> +	for (i = 0; i < priv->num_crtcs; i++)
> +		drm_crtc_vblank_off(priv->crtcs[i]);
> +
> +	priv->fbdev = omap_fbdev_init(ddev);
> +
> +	drm_kms_helper_poll_init(ddev);
> +
> +	/*
> +	 * Register the DRM device with the core and the connectors with
> +	 * sysfs.
> +	 */
> +	ret = drm_dev_register(ddev, 0);
> +	if (ret)
> +		goto err_cleanup_helpers;
> +
> +	return 0;
> +
> +err_cleanup_helpers:
> +	drm_kms_helper_poll_fini(ddev);
> +	if (priv->fbdev)
> +		omap_fbdev_free(ddev);
> +	drm_vblank_cleanup(ddev);
> +err_cleanup_modeset:
> +	drm_mode_config_cleanup(ddev);
> +	omap_drm_irq_uninstall(ddev);
> +err_free_drm_dev:
> +	omap_gem_deinit(ddev);
> +	drm_dev_unref(ddev);
> +err_free_priv:
> +	destroy_workqueue(priv->wq);
> +	kfree(priv);
> +err_disconnect_dssdevs:
> +	omap_disconnect_dssdevs();
> +err_crtc_uninit:
> +	omap_crtc_pre_uninit();
> +	return ret;
>  }
>  
> -static int pdev_remove(struct platform_device *device)
> +static int pdev_remove(struct platform_device *pdev)
>  {
> +	struct drm_device *ddev = platform_get_drvdata(pdev);
> +	struct omap_drm_private *priv = ddev->dev_private;
> +
>  	DBG("");
>  
> -	drm_put_dev(platform_get_drvdata(device));
> +	drm_dev_unregister(ddev);
> +
> +	drm_kms_helper_poll_fini(ddev);
> +
> +	if (priv->fbdev)
> +		omap_fbdev_free(ddev);
> +
> +	drm_mode_config_cleanup(ddev);
> +
> +	omap_drm_irq_uninstall(ddev);
> +	omap_gem_deinit(ddev);
> +
> +	drm_dev_unref(ddev);
> +
> +	destroy_workqueue(priv->wq);
> +	kfree(priv);
>  
>  	omap_disconnect_dssdevs();
>  	omap_crtc_pre_uninit();
> 

The old code calls drm_vblank_cleanup(), and the probe's error handling
calls that, but not remove. Is that correct?

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 22/22] drm: omapdrm: Perform initialization/cleanup at probe/remove time
  2016-12-16 12:44   ` Tomi Valkeinen
@ 2016-12-16 13:54     ` Laurent Pinchart
  0 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-16 13:54 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: dri-devel

Hi Tomi,

On Friday 16 Dec 2016 14:44:26 Tomi Valkeinen wrote:
> On 14/12/16 02:27, Laurent Pinchart wrote:
> > The drm driver .load() operation is prone to race conditions as it
> > initializes the driver after registering the device nodes. Its usage is
> > deprecated, inline it in the probe function and call drm_dev_alloc() and
> > drm_dev_register() explicitly.
> > 
> > For consistency inline the .unload() handler in the remove function as
> > well.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > Changes since v1:
> > 
> > - Call drm_kms_helper_poll_fini() before omap_fbdev_free() in the remove
> > 
> >   handler.
> > 
> > - Keep storing drm_device in the platform device private data.
> > ---
> > 
> >  drivers/gpu/drm/omapdrm/omap_connector.c |   2 -
> >  drivers/gpu/drm/omapdrm/omap_drv.c       | 212 +++++++++++++-------------
> >  2 files changed, 107 insertions(+), 107 deletions(-)

[snip]

> > diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c
> > b/drivers/gpu/drm/omapdrm/omap_drv.c index 0a2d461d62cf..a3b37823b271
> > 100644
> > --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> > +++ b/drivers/gpu/drm/omapdrm/omap_drv.c

[snip]

> > @@ -837,30 +741,128 @@ static struct drm_driver omap_drm_driver = {
> >  	.patchlevel = DRIVER_PATCHLEVEL,
> >  };
> > 
> > -static int pdev_probe(struct platform_device *device)
> > +static int pdev_probe(struct platform_device *pdev)
> >  {
> > -	int r;
> > +	struct omap_drm_platform_data *pdata = pdev->dev.platform_data;
> > +	struct omap_drm_private *priv;
> > +	struct drm_device *ddev;
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	DBG("%s", pdev->name);
> > 
> >  	if (omapdss_is_initialized() == false)
> >  		return -EPROBE_DEFER;
> >  	
> >  	omap_crtc_pre_init();
> > 
> > -	r = omap_connect_dssdevs();
> > -	if (r) {
> > +	ret = omap_connect_dssdevs();
> > +	if (ret) {
> >  		omap_crtc_pre_uninit();
> > -		return r;
> > +		goto err_crtc_uninit;
> 
> This calls omap_crtc_pre_uninit here and in the err handler.

Oops, will fix.

> > +	}
> > +
> > +	/* Allocate and initialize the driver private structure. */
> > +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > +	if (!priv) {
> > +		ret = -ENOMEM;
> > +		goto err_disconnect_dssdevs;
> > +	}
> > +
> > +	priv->omaprev = pdata->omaprev;
> > +	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
> > +
> > +	init_waitqueue_head(&priv->commit.wait);
> > +	spin_lock_init(&priv->commit.lock);
> > +	spin_lock_init(&priv->list_lock);
> > +	INIT_LIST_HEAD(&priv->obj_list);
> > +
> > +	/* Allocate and initialize the DRM device. */
> > +	ddev = drm_dev_alloc(&omap_drm_driver, &pdev->dev);
> > +	if (IS_ERR(ddev)) {
> > +		ret = PTR_ERR(ddev);
> > +		goto err_free_priv;
> > +	}
> > +
> > +	ddev->dev_private = priv;
> > +	platform_set_drvdata(pdev, ddev);
> > +
> > +	omap_gem_init(ddev);
> > +
> > +	ret = omap_modeset_init(ddev);
> > +	if (ret) {
> > +		dev_err(&pdev->dev, "omap_modeset_init failed: ret=%d\n", 
ret);
> > +		goto err_free_drm_dev;
> > +	}
> > +
> > +	/* Initialize vblank handling, start with all CRTCs disabled. */
> > +	ret = drm_vblank_init(ddev, priv->num_crtcs);
> > +	if (ret) {
> > +		dev_err(&pdev->dev, "could not init vblank\n");
> > +		goto err_cleanup_modeset;
> >  	}
> > 
> > -	DBG("%s", device->name);
> > -	return drm_platform_init(&omap_drm_driver, device);
> > +	for (i = 0; i < priv->num_crtcs; i++)
> > +		drm_crtc_vblank_off(priv->crtcs[i]);
> > +
> > +	priv->fbdev = omap_fbdev_init(ddev);
> > +
> > +	drm_kms_helper_poll_init(ddev);
> > +
> > +	/*
> > +	 * Register the DRM device with the core and the connectors with
> > +	 * sysfs.
> > +	 */
> > +	ret = drm_dev_register(ddev, 0);
> > +	if (ret)
> > +		goto err_cleanup_helpers;
> > +
> > +	return 0;
> > +
> > +err_cleanup_helpers:
> > +	drm_kms_helper_poll_fini(ddev);
> > +	if (priv->fbdev)
> > +		omap_fbdev_free(ddev);
> > +	drm_vblank_cleanup(ddev);
> > +err_cleanup_modeset:
> > +	drm_mode_config_cleanup(ddev);
> > +	omap_drm_irq_uninstall(ddev);
> > +err_free_drm_dev:
> > +	omap_gem_deinit(ddev);
> > +	drm_dev_unref(ddev);
> > +err_free_priv:
> > +	destroy_workqueue(priv->wq);
> > +	kfree(priv);
> > +err_disconnect_dssdevs:
> > +	omap_disconnect_dssdevs();
> > +err_crtc_uninit:
> > +	omap_crtc_pre_uninit();
> > +	return ret;
> >  }
> > 
> > -static int pdev_remove(struct platform_device *device)
> > +static int pdev_remove(struct platform_device *pdev)
> >  {
> > +	struct drm_device *ddev = platform_get_drvdata(pdev);
> > +	struct omap_drm_private *priv = ddev->dev_private;
> > +
> >  	DBG("");
> > 
> > -	drm_put_dev(platform_get_drvdata(device));
> > +	drm_dev_unregister(ddev);
> > +
> > +	drm_kms_helper_poll_fini(ddev);
> > +
> > +	if (priv->fbdev)
> > +		omap_fbdev_free(ddev);
> > +
> > +	drm_mode_config_cleanup(ddev);
> > +
> > +	omap_drm_irq_uninstall(ddev);
> > +	omap_gem_deinit(ddev);
> > +
> > +	drm_dev_unref(ddev);
> > +
> > +	destroy_workqueue(priv->wq);
> > +	kfree(priv);
> > 
> >  	omap_disconnect_dssdevs();
> >  	omap_crtc_pre_uninit();
> 
> The old code calls drm_vblank_cleanup(), and the probe's error handling
> calls that, but not remove. Is that correct?

Now that drm_vblank_cleanup() is called by drm_dev_release() we can drop the 
call from the probe error path. It used to be needed as the function was 
called from drm_dev_unregister().

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4.1 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active
  2016-12-14  0:27 ` [PATCH v4 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active Laurent Pinchart
  2016-12-15 12:52   ` Tomi Valkeinen
@ 2016-12-18  2:12   ` Laurent Pinchart
  2016-12-19  9:06     ` Tomi Valkeinen
  1 sibling, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-18  2:12 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Instead of going through a complicated private IRQ registration
mechanism, handle the vblank interrupt activation with the standard
drm_crtc_vblank_get() and drm_crtc_vblank_put() mechanism. This will let
the DRM core keep the vblank interrupt enabled as long as needed to
update the frame counter.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v4:

- Fix race condition between .atomic_flush() and vblank IRQ
- Make sure WARN_ON() don't have side effects
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 79 ++++++++++++++++---------------------
 drivers/gpu/drm/omapdrm/omap_drv.h  |  1 +
 drivers/gpu/drm/omapdrm/omap_irq.c  |  4 +-
 3 files changed, 37 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 827ac46a6d5e..046d199ef036 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -36,8 +36,6 @@ struct omap_crtc {
 
 	struct videomode vm;
 
-	struct omap_drm_irq vblank_irq;
-
 	bool ignore_digit_sync_lost;
 
 	bool enabled;
@@ -275,22 +273,6 @@ static const struct dss_mgr_ops mgr_ops = {
  * Setup, Flush and Page Flip
  */
 
-static void omap_crtc_complete_page_flip(struct drm_crtc *crtc)
-{
-	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-	struct drm_pending_vblank_event *event;
-	struct drm_device *dev = crtc->dev;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->event_lock, flags);
-	event = omap_crtc->event;
-	omap_crtc->event = NULL;
-
-	if (event)
-		drm_crtc_send_vblank_event(crtc, event);
-	spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
 void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
@@ -304,30 +286,38 @@ void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus)
 	DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus);
 }
 
-static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+void omap_crtc_vblank_irq(struct drm_crtc *crtc)
 {
-	struct omap_crtc *omap_crtc =
-			container_of(irq, struct omap_crtc, vblank_irq);
-	struct drm_device *dev = omap_crtc->base.dev;
-	struct drm_crtc *crtc = &omap_crtc->base;
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	bool pending;
 
-	if (dispc_mgr_go_busy(omap_crtc->channel))
+	spin_lock(&crtc->dev->event_lock);
+	/*
+	 * If the dispc is busy we're racing the flush operation. Try again on
+	 * the next vblank interrupt.
+	 */
+	if (dispc_mgr_go_busy(omap_crtc->channel)) {
+		spin_unlock(&crtc->dev->event_lock);
 		return;
+	}
 
-	DBG("%s: apply done", omap_crtc->name);
-
-	__omap_irq_unregister(dev, &omap_crtc->vblank_irq);
+	/* Send the vblank event if one has been requested. */
+	if (omap_crtc->event) {
+		drm_crtc_send_vblank_event(crtc, omap_crtc->event);
+		omap_crtc->event = NULL;
+	}
 
-	spin_lock(&crtc->dev->event_lock);
-	WARN_ON(!omap_crtc->pending);
+	pending = omap_crtc->pending;
 	omap_crtc->pending = false;
 	spin_unlock(&crtc->dev->event_lock);
 
-	/* wake up userspace */
-	omap_crtc_complete_page_flip(&omap_crtc->base);
+	if (pending)
+		drm_crtc_vblank_put(crtc);
 
-	/* wake up omap_atomic_complete */
+	/* Wake up omap_atomic_complete. */
 	wake_up(&omap_crtc->pending_wait);
+
+	DBG("%s: apply done", omap_crtc->name);
 }
 
 /* -----------------------------------------------------------------------------
@@ -340,8 +330,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
 
 	DBG("%s", omap_crtc->name);
 
-	WARN_ON(omap_crtc->vblank_irq.registered);
-
 	drm_crtc_cleanup(crtc);
 
 	kfree(omap_crtc);
@@ -350,17 +338,18 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
 static void omap_crtc_enable(struct drm_crtc *crtc)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	int ret;
 
 	DBG("%s", omap_crtc->name);
 
 	spin_lock_irq(&crtc->dev->event_lock);
+	drm_crtc_vblank_on(crtc);
+	ret = drm_crtc_vblank_get(crtc);
+	WARN_ON(ret != 0);
+
 	WARN_ON(omap_crtc->pending);
 	omap_crtc->pending = true;
 	spin_unlock_irq(&crtc->dev->event_lock);
-
-	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
-
-	drm_crtc_vblank_on(crtc);
 }
 
 static void omap_crtc_disable(struct drm_crtc *crtc)
@@ -413,8 +402,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 				   struct drm_crtc_state *old_crtc_state)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-
-	WARN_ON(omap_crtc->vblank_irq.registered);
+	int ret;
 
 	if (crtc->state->color_mgmt_changed) {
 		struct drm_color_lut *lut = NULL;
@@ -441,16 +429,18 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DBG("%s: GO", omap_crtc->name);
 
+	ret = drm_crtc_vblank_get(crtc);
+	WARN_ON(ret != 0);
+
 	spin_lock_irq(&crtc->dev->event_lock);
+	dispc_mgr_go(omap_crtc->channel);
+
 	WARN_ON(omap_crtc->pending);
 	omap_crtc->pending = true;
 
 	if (crtc->state->event)
 		omap_crtc->event = crtc->state->event;
 	spin_unlock_irq(&crtc->dev->event_lock);
-
-	dispc_mgr_go(omap_crtc->channel);
-	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
 }
 
 static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc,
@@ -571,9 +561,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 	omap_crtc->channel = channel;
 	omap_crtc->name = channel_names[channel];
 
-	omap_crtc->vblank_irq.irqmask = pipe2vbl(crtc);
-	omap_crtc->vblank_irq.irq = omap_crtc_vblank_irq;
-
 	ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
 					&omap_crtc_funcs, NULL);
 	if (ret < 0) {
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 851629e8704e..9437acc1c541 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -155,6 +155,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, enum omap_channel channel, int id);
 int omap_crtc_wait_pending(struct drm_crtc *crtc);
 void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
+void omap_crtc_vblank_irq(struct drm_crtc *crtc);
 
 struct drm_plane *omap_plane_init(struct drm_device *dev,
 		int id, enum drm_plane_type type,
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index e1925fa6d849..1c826907dead 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -245,8 +245,10 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 		struct drm_crtc *crtc = priv->crtcs[id];
 		enum omap_channel channel = omap_crtc_channel(crtc);
 
-		if (irqstatus & pipe2vbl(crtc))
+		if (irqstatus & pipe2vbl(crtc)) {
 			drm_handle_vblank(dev, id);
+			omap_crtc_vblank_irq(crtc);
+		}
 
 		if (irqstatus & dispc_mgr_get_sync_lost_irq(channel))
 			omap_crtc_error_irq(crtc, irqstatus);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4.1 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active
  2016-12-18  2:12   ` [PATCH v4.1 " Laurent Pinchart
@ 2016-12-19  9:06     ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-19  9:06 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 883 bytes --]

On 18/12/16 04:12, Laurent Pinchart wrote:
> Instead of going through a complicated private IRQ registration
> mechanism, handle the vblank interrupt activation with the standard
> drm_crtc_vblank_get() and drm_crtc_vblank_put() mechanism. This will let
> the DRM core keep the vblank interrupt enabled as long as needed to
> update the frame counter.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v4:
> 
> - Fix race condition between .atomic_flush() and vblank IRQ
> - Make sure WARN_ON() don't have side effects
> ---
>  drivers/gpu/drm/omapdrm/omap_crtc.c | 79 ++++++++++++++++---------------------
>  drivers/gpu/drm/omapdrm/omap_drv.h  |  1 +
>  drivers/gpu/drm/omapdrm/omap_irq.c  |  4 +-
>  3 files changed, 37 insertions(+), 47 deletions(-)

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4.1 22/22] drm: omapdrm: Perform initialization/cleanup at probe/remove time
  2016-12-14  0:27 ` [PATCH v4 22/22] drm: omapdrm: Perform initialization/cleanup at probe/remove time Laurent Pinchart
  2016-12-16 12:44   ` Tomi Valkeinen
@ 2016-12-19  9:15   ` Laurent Pinchart
  2016-12-19  9:25     ` Tomi Valkeinen
  1 sibling, 1 reply; 52+ messages in thread
From: Laurent Pinchart @ 2016-12-19  9:15 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The drm driver .load() operation is prone to race conditions as it
initializes the driver after registering the device nodes. Its usage is
deprecated, inline it in the probe function and call drm_dev_alloc() and
drm_dev_register() explicitly.

For consistency inline the .unload() handler in the remove function as
well.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v4:

- Dropped drm_vblank_cleanup() in probe error path
- Removed a duplicate call to omap_crtc_pre_uninit() in probe

Changes since v1:

- Call drm_kms_helper_poll_fini() before omap_fbdev_free() in the remove
  handler.
- Keep storing drm_device in the platform device private data.
---
 drivers/gpu/drm/omapdrm/omap_connector.c |   2 -
 drivers/gpu/drm/omapdrm/omap_drv.c       | 211 +++++++++++++++----------------
 2 files changed, 105 insertions(+), 108 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 691cffebb76e..f90e2d22c5ec 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -240,8 +240,6 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
 	connector->interlace_allowed = 1;
 	connector->doublescan_allowed = 0;
 
-	drm_connector_register(connector);
-
 	return connector;
 
 fail:
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 0a2d461d62cf..00aa214b7560 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -493,11 +493,6 @@ static int omap_modeset_init(struct drm_device *dev)
 	return 0;
 }
 
-static void omap_modeset_free(struct drm_device *dev)
-{
-	drm_mode_config_cleanup(dev);
-}
-
 /*
  * drm ioctl funcs
  */
@@ -633,95 +628,6 @@ static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] =
  * drm driver funcs
  */
 
-/**
- * load - setup chip and create an initial config
- * @dev: DRM device
- * @flags: startup flags
- *
- * The driver load routine has to do several things:
- *   - initialize the memory manager
- *   - allocate initial config memory
- *   - setup the DRM framebuffer with the allocated memory
- */
-static int dev_load(struct drm_device *dev, unsigned long flags)
-{
-	struct omap_drm_platform_data *pdata = dev->dev->platform_data;
-	struct omap_drm_private *priv;
-	unsigned int i;
-	int ret;
-
-	DBG("load: dev=%p", dev);
-
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->omaprev = pdata->omaprev;
-
-	dev->dev_private = priv;
-
-	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
-	init_waitqueue_head(&priv->commit.wait);
-	spin_lock_init(&priv->commit.lock);
-
-	spin_lock_init(&priv->list_lock);
-	INIT_LIST_HEAD(&priv->obj_list);
-
-	omap_gem_init(dev);
-
-	ret = omap_modeset_init(dev);
-	if (ret) {
-		dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
-		dev->dev_private = NULL;
-		kfree(priv);
-		return ret;
-	}
-
-	/* Initialize vblank handling, start with all CRTCs disabled. */
-	ret = drm_vblank_init(dev, priv->num_crtcs);
-	if (ret)
-		dev_warn(dev->dev, "could not init vblank\n");
-
-	for (i = 0; i < priv->num_crtcs; i++)
-		drm_crtc_vblank_off(priv->crtcs[i]);
-
-	priv->fbdev = omap_fbdev_init(dev);
-
-	/* store off drm_device for use in pm ops */
-	dev_set_drvdata(dev->dev, dev);
-
-	drm_kms_helper_poll_init(dev);
-
-	return 0;
-}
-
-static int dev_unload(struct drm_device *dev)
-{
-	struct omap_drm_private *priv = dev->dev_private;
-
-	DBG("unload: dev=%p", dev);
-
-	drm_kms_helper_poll_fini(dev);
-
-	if (priv->fbdev)
-		omap_fbdev_free(dev);
-
-	omap_modeset_free(dev);
-	omap_gem_deinit(dev);
-
-	destroy_workqueue(priv->wq);
-
-	drm_vblank_cleanup(dev);
-	omap_drm_irq_uninstall(dev);
-
-	kfree(dev->dev_private);
-	dev->dev_private = NULL;
-
-	dev_set_drvdata(dev->dev, NULL);
-
-	return 0;
-}
-
 static int dev_open(struct drm_device *dev, struct drm_file *file)
 {
 	file->driver_priv = NULL;
@@ -806,8 +712,6 @@ static const struct file_operations omapdriver_fops = {
 static struct drm_driver omap_drm_driver = {
 	.driver_features = DRIVER_MODESET | DRIVER_GEM  | DRIVER_PRIME |
 		DRIVER_ATOMIC,
-	.load = dev_load,
-	.unload = dev_unload,
 	.open = dev_open,
 	.lastclose = dev_lastclose,
 	.get_vblank_counter = drm_vblank_no_hw_counter,
@@ -837,30 +741,125 @@ static struct drm_driver omap_drm_driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
-static int pdev_probe(struct platform_device *device)
+static int pdev_probe(struct platform_device *pdev)
 {
-	int r;
+	struct omap_drm_platform_data *pdata = pdev->dev.platform_data;
+	struct omap_drm_private *priv;
+	struct drm_device *ddev;
+	unsigned int i;
+	int ret;
+
+	DBG("%s", pdev->name);
 
 	if (omapdss_is_initialized() == false)
 		return -EPROBE_DEFER;
 
 	omap_crtc_pre_init();
 
-	r = omap_connect_dssdevs();
-	if (r) {
-		omap_crtc_pre_uninit();
-		return r;
+	ret = omap_connect_dssdevs();
+	if (ret)
+		goto err_crtc_uninit;
+
+	/* Allocate and initialize the driver private structure. */
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err_disconnect_dssdevs;
+	}
+
+	priv->omaprev = pdata->omaprev;
+	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
+
+	init_waitqueue_head(&priv->commit.wait);
+	spin_lock_init(&priv->commit.lock);
+	spin_lock_init(&priv->list_lock);
+	INIT_LIST_HEAD(&priv->obj_list);
+
+	/* Allocate and initialize the DRM device. */
+	ddev = drm_dev_alloc(&omap_drm_driver, &pdev->dev);
+	if (IS_ERR(ddev)) {
+		ret = PTR_ERR(ddev);
+		goto err_free_priv;
+	}
+
+	ddev->dev_private = priv;
+	platform_set_drvdata(pdev, ddev);
+
+	omap_gem_init(ddev);
+
+	ret = omap_modeset_init(ddev);
+	if (ret) {
+		dev_err(&pdev->dev, "omap_modeset_init failed: ret=%d\n", ret);
+		goto err_free_drm_dev;
+	}
+
+	/* Initialize vblank handling, start with all CRTCs disabled. */
+	ret = drm_vblank_init(ddev, priv->num_crtcs);
+	if (ret) {
+		dev_err(&pdev->dev, "could not init vblank\n");
+		goto err_cleanup_modeset;
 	}
 
-	DBG("%s", device->name);
-	return drm_platform_init(&omap_drm_driver, device);
+	for (i = 0; i < priv->num_crtcs; i++)
+		drm_crtc_vblank_off(priv->crtcs[i]);
+
+	priv->fbdev = omap_fbdev_init(ddev);
+
+	drm_kms_helper_poll_init(ddev);
+
+	/*
+	 * Register the DRM device with the core and the connectors with
+	 * sysfs.
+	 */
+	ret = drm_dev_register(ddev, 0);
+	if (ret)
+		goto err_cleanup_helpers;
+
+	return 0;
+
+err_cleanup_helpers:
+	drm_kms_helper_poll_fini(ddev);
+	if (priv->fbdev)
+		omap_fbdev_free(ddev);
+err_cleanup_modeset:
+	drm_mode_config_cleanup(ddev);
+	omap_drm_irq_uninstall(ddev);
+err_free_drm_dev:
+	omap_gem_deinit(ddev);
+	drm_dev_unref(ddev);
+err_free_priv:
+	destroy_workqueue(priv->wq);
+	kfree(priv);
+err_disconnect_dssdevs:
+	omap_disconnect_dssdevs();
+err_crtc_uninit:
+	omap_crtc_pre_uninit();
+	return ret;
 }
 
-static int pdev_remove(struct platform_device *device)
+static int pdev_remove(struct platform_device *pdev)
 {
+	struct drm_device *ddev = platform_get_drvdata(pdev);
+	struct omap_drm_private *priv = ddev->dev_private;
+
 	DBG("");
 
-	drm_put_dev(platform_get_drvdata(device));
+	drm_dev_unregister(ddev);
+
+	drm_kms_helper_poll_fini(ddev);
+
+	if (priv->fbdev)
+		omap_fbdev_free(ddev);
+
+	drm_mode_config_cleanup(ddev);
+
+	omap_drm_irq_uninstall(ddev);
+	omap_gem_deinit(ddev);
+
+	drm_dev_unref(ddev);
+
+	destroy_workqueue(priv->wq);
+	kfree(priv);
 
 	omap_disconnect_dssdevs();
 	omap_crtc_pre_uninit();
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4.1 22/22] drm: omapdrm: Perform initialization/cleanup at probe/remove time
  2016-12-19  9:15   ` [PATCH v4.1 " Laurent Pinchart
@ 2016-12-19  9:25     ` Tomi Valkeinen
  0 siblings, 0 replies; 52+ messages in thread
From: Tomi Valkeinen @ 2016-12-19  9:25 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 1063 bytes --]

On 19/12/16 11:15, Laurent Pinchart wrote:
> The drm driver .load() operation is prone to race conditions as it
> initializes the driver after registering the device nodes. Its usage is
> deprecated, inline it in the probe function and call drm_dev_alloc() and
> drm_dev_register() explicitly.
> 
> For consistency inline the .unload() handler in the remove function as
> well.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v4:
> 
> - Dropped drm_vblank_cleanup() in probe error path
> - Removed a duplicate call to omap_crtc_pre_uninit() in probe
> 
> Changes since v1:
> 
> - Call drm_kms_helper_poll_fini() before omap_fbdev_free() in the remove
>   handler.
> - Keep storing drm_device in the platform device private data.
> ---
>  drivers/gpu/drm/omapdrm/omap_connector.c |   2 -
>  drivers/gpu/drm/omapdrm/omap_drv.c       | 211 +++++++++++++++----------------
>  2 files changed, 105 insertions(+), 108 deletions(-)

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2016-12-19  9:25 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-14  0:27 [PATCH v4 00/22] OMAP DRM fixes and improvements Laurent Pinchart
2016-12-14  0:27 ` [PATCH v4 01/22] drm: omapdrm: fb: Limit number of planes per framebuffer to two Laurent Pinchart
2016-12-14  0:27 ` [PATCH v4 02/22] drm: omapdrm: fb: Use format information provided by the DRM core Laurent Pinchart
2016-12-14 10:07   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 03/22] drm: omapdrm: fb: Simplify objects lookup when creating framebuffer Laurent Pinchart
2016-12-14  0:27 ` [PATCH v4 04/22] drm: omapdrm: fb: Simplify mode command checks " Laurent Pinchart
2016-12-14  0:27 ` [PATCH v4 05/22] drm: omapdrm: fb: Turn framebuffer creation error messages into debug Laurent Pinchart
2016-12-14  0:27 ` [PATCH v4 06/22] drm: omapdrm: Handle FIFO underflow IRQs internally Laurent Pinchart
2016-12-14 10:22   ` Tomi Valkeinen
2016-12-14 11:48     ` Laurent Pinchart
2016-12-14 13:13       ` Tomi Valkeinen
2016-12-15  9:02       ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 07/22] drm: omapdrm: Handle CRTC error IRQs directly Laurent Pinchart
2016-12-14  0:27 ` [PATCH v4 08/22] drm: omapdrm: Handle OCP error IRQ directly Laurent Pinchart
2016-12-14 10:24   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 09/22] drm: omapdrm: Replace DSS manager state check with omapdrm CRTC state Laurent Pinchart
2016-12-14 10:36   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 10/22] drm: omapdrm: Let the DRM core skip plane commit on inactive CRTCs Laurent Pinchart
2016-12-14 10:43   ` Tomi Valkeinen
2016-12-14 11:26     ` Laurent Pinchart
2016-12-14  0:27 ` [PATCH v4 11/22] drm: omapdrm: Check the CRTC software state at enable/disable time Laurent Pinchart
2016-12-14 14:54   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 12/22] drm: omapdrm: Prevent processing the same event multiple times Laurent Pinchart
2016-12-15 12:20   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 13/22] drm: omapdrm: Use a spinlock to protect the CRTC pending flag Laurent Pinchart
2016-12-14  0:27 ` [PATCH v4 14/22] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active Laurent Pinchart
2016-12-15 12:52   ` Tomi Valkeinen
2016-12-15 14:51     ` Laurent Pinchart
2016-12-15 14:56       ` Tomi Valkeinen
2016-12-18  2:12   ` [PATCH v4.1 " Laurent Pinchart
2016-12-19  9:06     ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 15/22] drm: omapdrm: Don't expose the omap_irq_(un)register() functions Laurent Pinchart
2016-12-15 12:56   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 16/22] drm: omapdrm: Remove unused parameter from omap_drm_irq handler Laurent Pinchart
2016-12-15 12:57   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 17/22] drm: omapdrm: Don't call DISPC power handling in IRQ wait functions Laurent Pinchart
2016-12-15 13:00   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 18/22] drm: omapdrm: Inline the pipe2vbl function Laurent Pinchart
2016-12-14 10:25   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 19/22] drm: omapdrm: Simplify IRQ wait implementation Laurent Pinchart
2016-12-16 12:24   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 20/22] drm: omapdrm: Remove global variables Laurent Pinchart
2016-12-16 12:31   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 21/22] drm: omapdrm: Use sizeof(*var) instead of sizeof(type) for structures Laurent Pinchart
2016-12-15 13:02   ` Tomi Valkeinen
2016-12-14  0:27 ` [PATCH v4 22/22] drm: omapdrm: Perform initialization/cleanup at probe/remove time Laurent Pinchart
2016-12-16 12:44   ` Tomi Valkeinen
2016-12-16 13:54     ` Laurent Pinchart
2016-12-19  9:15   ` [PATCH v4.1 " Laurent Pinchart
2016-12-19  9:25     ` Tomi Valkeinen
2016-12-14  8:48 ` [PATCH v4 00/22] OMAP DRM fixes and improvements Tomi Valkeinen
2016-12-14 11:50   ` Laurent Pinchart

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.