To avoid race condition issue, we should protect the function ipu_dmfc_init_channel() with the mutex dmfc->priv->mutex, since it configures the register DMFC_GENERAL1 at runtime which contains several control bits for various display channels. This matches better with fine grained locking logic in upper layer.
Signed-off-by: Liu Ying gnuiyl@gmail.com --- drivers/gpu/ipu-v3/ipu-dmfc.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c index 042c395..129ccfa 100644 --- a/drivers/gpu/ipu-v3/ipu-dmfc.c +++ b/drivers/gpu/ipu-v3/ipu-dmfc.c @@ -355,6 +355,8 @@ int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width) struct ipu_dmfc_priv *priv = dmfc->priv; u32 dmfc_gen1;
+ mutex_lock(&priv->mutex); + dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines) @@ -364,6 +366,8 @@ int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width)
writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
+ mutex_unlock(&priv->mutex); + return 0; } EXPORT_SYMBOL_GPL(ipu_dmfc_init_channel);
Since the function ipu_dmfc_init_channel() always returns zero, we may change the return type to void to simplify the code.
Signed-off-by: Liu Ying gnuiyl@gmail.com --- drivers/gpu/drm/imx/ipuv3-plane.c | 6 +----- drivers/gpu/ipu-v3/ipu-dmfc.c | 4 +--- include/video/imx-ipu-v3.h | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index d078373..0faf84a 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -200,11 +200,7 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, } }
- ret = ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w); - if (ret) { - dev_err(dev, "initializing dmfc channel failed with %d\n", ret); - return ret; - } + ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w);
ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc, calc_bandwidth(crtc_w, crtc_h, diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c index 129ccfa..3aa9878 100644 --- a/drivers/gpu/ipu-v3/ipu-dmfc.c +++ b/drivers/gpu/ipu-v3/ipu-dmfc.c @@ -350,7 +350,7 @@ out: } EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth);
-int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width) +void ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width) { struct ipu_dmfc_priv *priv = dmfc->priv; u32 dmfc_gen1; @@ -367,8 +367,6 @@ int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width) writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
mutex_unlock(&priv->mutex); - - return 0; } EXPORT_SYMBOL_GPL(ipu_dmfc_init_channel);
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h index eeba753..07dfc41 100644 --- a/include/video/imx-ipu-v3.h +++ b/include/video/imx-ipu-v3.h @@ -236,7 +236,7 @@ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc); int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc, unsigned long bandwidth_mbs, int burstsize); void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc); -int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width); +void ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width); struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel); void ipu_dmfc_put(struct dmfc_channel *dmfc);
The function name 'ipu_dmfc_config_wait4eot' matches the implementation of the function better than 'ipu_dmfc_init_channel', since it only touches the wait4eot bits.
Signed-off-by: Liu Ying gnuiyl@gmail.com --- drivers/gpu/drm/imx/ipuv3-plane.c | 2 +- drivers/gpu/ipu-v3/ipu-dmfc.c | 4 ++-- include/video/imx-ipu-v3.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 0faf84a..cab8a45 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -200,7 +200,7 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, } }
- ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w); + ipu_dmfc_config_wait4eot(ipu_plane->dmfc, crtc_w);
ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc, calc_bandwidth(crtc_w, crtc_h, diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c index 3aa9878..837b1ec2 100644 --- a/drivers/gpu/ipu-v3/ipu-dmfc.c +++ b/drivers/gpu/ipu-v3/ipu-dmfc.c @@ -350,7 +350,7 @@ out: } EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth);
-void ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width) +void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width) { struct ipu_dmfc_priv *priv = dmfc->priv; u32 dmfc_gen1; @@ -368,7 +368,7 @@ void ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width)
mutex_unlock(&priv->mutex); } -EXPORT_SYMBOL_GPL(ipu_dmfc_init_channel); +EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel) { diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h index 07dfc41..8abf16b 100644 --- a/include/video/imx-ipu-v3.h +++ b/include/video/imx-ipu-v3.h @@ -236,7 +236,7 @@ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc); int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc, unsigned long bandwidth_mbs, int burstsize); void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc); -void ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width); +void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width); struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel); void ipu_dmfc_put(struct dmfc_channel *dmfc);
Just as the function ipu_dmfc_config_wait4eot() tells, the DMFC wait4eot bit depends on the number of DMFC slots to be used, so it should be called after the slots are determined in the function ipu_dmfc_alloc_bandwidth(). Based on tests, this patch may eliminate display distortion issue on overlay plane with small resolutions. To reproduce the issue, we may run this drm modetest case - 'modetest -P 19:64x64'.
Signed-off-by: Liu Ying gnuiyl@gmail.com --- drivers/gpu/drm/imx/ipuv3-plane.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index cab8a45..afec9f6 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -200,8 +200,6 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, } }
- ipu_dmfc_config_wait4eot(ipu_plane->dmfc, crtc_w); - ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc, calc_bandwidth(crtc_w, crtc_h, calc_vref(mode)), 64); @@ -210,6 +208,8 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, return ret; }
+ ipu_dmfc_config_wait4eot(ipu_plane->dmfc, crtc_w); + ipu_cpmem_zero(ipu_plane->ipu_ch); ipu_cpmem_set_resolution(ipu_plane->ipu_ch, src_w, src_h); ret = ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->pixel_format);
Hi Liu,
Am Montag, den 14.03.2016, 16:10 +0800 schrieb Liu Ying:
To avoid race condition issue, we should protect the function ipu_dmfc_init_channel() with the mutex dmfc->priv->mutex, since it configures the register DMFC_GENERAL1 at runtime which contains several control bits for various display channels. This matches better with fine grained locking logic in upper layer.
Applied all four patches, thank you.
regards Philipp
dri-devel@lists.freedesktop.org