2016-03-07 22:01:27

by Doug Anderson

[permalink] [raw]
Subject: [PATCH v2 1/5] drm/rockchip: dw_hdmi: Call drm_encoder_cleanup() in error path

The drm_encoder_cleanup() was missing both from the error path of
dw_hdmi_rockchip_bind(). This caused a crash when slub_debug was
enabled and we ended up deferring probe of HDMI at boot.

This call isn't needed from unbind() because if dw_hdmi_bind() returns
no error then it takes over the job of freeing the encoder (in
dw_hdmi_unbind).

Signed-off-by: Douglas Anderson <[email protected]>
---
Changes in v2: None

drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 3d3cf2f8891e..88776aba984e 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -293,7 +293,16 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
DRM_MODE_ENCODER_TMDS, NULL);

- return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
+ ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
+
+ /*
+ * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
+ * which would have called the encoder cleanup. Do it manually.
+ */
+ if (ret)
+ drm_encoder_cleanup(encoder);
+
+ return ret;
}

static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
--
2.7.0.rc3.207.g0ac5344


2016-03-07 22:01:40

by Doug Anderson

[permalink] [raw]
Subject: [PATCH v2 5/5] drm/imx: dw_hdmi: Don't call platform_set_drvdata()

The IMX dw_hdmi driver just called platform_set_drvdata() to get
your hopes up that maybe, somehow, you'd be able to retrieve the 'struct
imx_hdmi' from a pointer to the 'struct device'. You can't. When
we call dw_hdmi_bind() the main driver calls dev_set_drvdata(), which
clobbers our setting.

Let's just remove the platform_set_drvdata() to avoid dashing people's
hopes.

Signed-off-by: Douglas Anderson <[email protected]>
---
Changes in v2:
- Don't call platform_set_drvdata() new for v2.

drivers/gpu/drm/imx/dw_hdmi-imx.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index c69c3142819c..a24631fdf4ad 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -225,8 +225,6 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
if (!iores)
return -ENXIO;

- platform_set_drvdata(pdev, hdmi);
-
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
/*
* If we failed to find the CRTC(s) which this encoder is
--
2.7.0.rc3.207.g0ac5344

2016-03-07 22:01:49

by Doug Anderson

[permalink] [raw]
Subject: [PATCH v2 4/5] drm/rockchip: dw_hdmi: Don't call platform_set_drvdata()

The Rockchip dw_hdmi driver just called platform_set_drvdata() to get
your hopes up that maybe, somehow, you'd be able to retrieve the 'struct
rockchip_hdmi' from a pointer to the 'struct device'. You can't. When
we call dw_hdmi_bind() the main driver calls dev_set_drvdata(), which
clobbers our setting.

Let's just remove the platform_set_drvdata() to avoid dashing people's
hopes.

Signed-off-by: Douglas Anderson <[email protected]>
---
Changes in v2:
- Don't call platform_set_drvdata() new for v2.

drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 88776aba984e..d5cfef75fc80 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -271,8 +271,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
if (!iores)
return -ENXIO;

- platform_set_drvdata(pdev, hdmi);
-
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
/*
* If we failed to find the CRTC(s) which this encoder is
--
2.7.0.rc3.207.g0ac5344

2016-03-07 22:01:57

by Doug Anderson

[permalink] [raw]
Subject: [PATCH v2 3/5] drm/rockchip: vop: Fix vop crtc cleanup

This fixes a few problems in the vop crtc cleanup (handling error
paths and cleanup upon exit):

* The vop_create_crtc() error path had an unsafe version of the
iterator used for iterating over all planes (though it was
destroying planes in the iterator so should have used the safe
version)

* vop_destroy_crtc() - wasn't calling vop_plane_destroy(), which made
slub_debug unhappy, at least if we ended up running this due to a
deferred probe.

* In vop_create_crtc() if we were missing the "port" device tree node
we would fail but not return an error (found by code inspection).

Fix these problems.

Signed-off-by: Douglas Anderson <[email protected]>
---
Changes in v2: None

drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index fd370548d7d7..f86f797f10fd 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1108,7 +1108,7 @@ static int vop_create_crtc(struct vop *vop)
const struct vop_data *vop_data = vop->data;
struct device *dev = vop->dev;
struct drm_device *drm_dev = vop->drm_dev;
- struct drm_plane *primary = NULL, *cursor = NULL, *plane;
+ struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
struct drm_crtc *crtc = &vop->crtc;
struct device_node *port;
int ret;
@@ -1148,7 +1148,7 @@ static int vop_create_crtc(struct vop *vop)
ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
&vop_crtc_funcs, NULL);
if (ret)
- return ret;
+ goto err_cleanup_planes;

drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);

@@ -1181,6 +1181,7 @@ static int vop_create_crtc(struct vop *vop)
if (!port) {
DRM_ERROR("no port node found in %s\n",
dev->of_node->full_name);
+ ret = -ENOENT;
goto err_cleanup_crtc;
}

@@ -1194,7 +1195,8 @@ static int vop_create_crtc(struct vop *vop)
err_cleanup_crtc:
drm_crtc_cleanup(crtc);
err_cleanup_planes:
- list_for_each_entry(plane, &drm_dev->mode_config.plane_list, head)
+ list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
+ head)
drm_plane_cleanup(plane);
return ret;
}
@@ -1202,9 +1204,28 @@ err_cleanup_planes:
static void vop_destroy_crtc(struct vop *vop)
{
struct drm_crtc *crtc = &vop->crtc;
+ struct drm_device *drm_dev = vop->drm_dev;
+ struct drm_plane *plane, *tmp;

rockchip_unregister_crtc_funcs(crtc);
of_node_put(crtc->port);
+
+ /*
+ * We need to cleanup the planes now. Why?
+ *
+ * The planes are "&vop->win[i].base". That means the memory is
+ * all part of the big "struct vop" chunk of memory. That memory
+ * was devm allocated and associated with this component. We need to
+ * free it ourselves before vop_unbind() finishes.
+ */
+ list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
+ head)
+ vop_plane_destroy(plane);
+
+ /*
+ * Destroy CRTC after vop_plane_destroy() since vop_disable_plane()
+ * references the CRTC.
+ */
drm_crtc_cleanup(crtc);
}

--
2.7.0.rc3.207.g0ac5344

2016-03-07 22:02:09

by Doug Anderson

[permalink] [raw]
Subject: [PATCH v2 2/5] drm/imx: dw_hdmi: Call drm_encoder_cleanup() in error path

The drm_encoder_cleanup() was missing both from the error path of
dw_hdmi_imx_bind(). This caused a crash when slub_debug was
enabled and we ended up deferring probe of HDMI at boot.

This call isn't needed from unbind() because if dw_hdmi_bind() returns
no error then it takes over the job of freeing the encoder (in
dw_hdmi_unbind).

Signed-off-by: Douglas Anderson <[email protected]>
---
Changes in v2:
- IMX patch new in v2

drivers/gpu/drm/imx/dw_hdmi-imx.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index 2a95d10e9d92..c69c3142819c 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -245,7 +245,16 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs,
DRM_MODE_ENCODER_TMDS, NULL);

- return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
+ ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
+
+ /*
+ * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
+ * which would have called the encoder cleanup. Do it manually.
+ */
+ if (ret)
+ drm_encoder_cleanup(encoder);
+
+ return ret;
}

static void dw_hdmi_imx_unbind(struct device *dev, struct device *master,
--
2.7.0.rc3.207.g0ac5344

2016-03-28 06:45:27

by Mark yao

[permalink] [raw]
Subject: Re: [PATCH v2 1/5] drm/rockchip: dw_hdmi: Call drm_encoder_cleanup() in error path

On 2016年03月08日 06:00, Douglas Anderson wrote:
> The drm_encoder_cleanup() was missing both from the error path of
> dw_hdmi_rockchip_bind(). This caused a crash when slub_debug was
> enabled and we ended up deferring probe of HDMI at boot.
>
> This call isn't needed from unbind() because if dw_hdmi_bind() returns
> no error then it takes over the job of freeing the encoder (in
> dw_hdmi_unbind).
>
> Signed-off-by: Douglas Anderson <[email protected]>

Hi Douglas

it seems has no doubt on these patch, and it works on my board, So I'd
like to apply following three patches.

[PATCH v2 1/5] drm/rockchip: dw_hdmi: Call drm_encoder_cleanup() in
error path
[PATCH v2 3/5] drm/rockchip: vop: Fix vop crtc cleanup
[PATCH v2 4/5] drm/rockchip: dw_hdmi: Don't call platform_set_drvdata()

Thanks for your fixes.

-- Mark Yao

2016-03-28 15:14:31

by Doug Anderson

[permalink] [raw]
Subject: Re: [PATCH v2 2/5] drm/imx: dw_hdmi: Call drm_encoder_cleanup() in error path

Hi,

On Mon, Mar 7, 2016 at 2:00 PM, Douglas Anderson <[email protected]> wrote:
> The drm_encoder_cleanup() was missing both from the error path of
> dw_hdmi_imx_bind(). This caused a crash when slub_debug was
> enabled and we ended up deferring probe of HDMI at boot.
>
> This call isn't needed from unbind() because if dw_hdmi_bind() returns
> no error then it takes over the job of freeing the encoder (in
> dw_hdmi_unbind).
>
> Signed-off-by: Douglas Anderson <[email protected]>
> ---
> Changes in v2:
> - IMX patch new in v2
>
> drivers/gpu/drm/imx/dw_hdmi-imx.c | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)

Mark picked up:

[PATCH v2 1/5] drm/rockchip: dw_hdmi: Call drm_encoder_cleanup() in error path
[PATCH v2 3/5] drm/rockchip: vop: Fix vop crtc cleanup
[PATCH v2 4/5] drm/rockchip: dw_hdmi: Don't call platform_set_drvdata()

...for Rockchip, as you can see at
<https://patchwork.kernel.org/patch/8523301/>.

Does someone want to pick up:
[PATCH v2 2/5] drm/imx: dw_hdmi: Call drm_encoder_cleanup() in error path
[PATCH v2 5/5] drm/imx: dw_hdmi: Don't call platform_set_drvdata()

Thanks!

-Doug

2016-03-30 13:36:42

by Philipp Zabel

[permalink] [raw]
Subject: Re: [PATCH v2 2/5] drm/imx: dw_hdmi: Call drm_encoder_cleanup() in error path

Hi Doug,

Am Montag, den 28.03.2016, 08:14 -0700 schrieb Doug Anderson:
> Hi,
>
> On Mon, Mar 7, 2016 at 2:00 PM, Douglas Anderson <[email protected]> wrote:
> > The drm_encoder_cleanup() was missing both from the error path of
> > dw_hdmi_imx_bind(). This caused a crash when slub_debug was
> > enabled and we ended up deferring probe of HDMI at boot.
> >
> > This call isn't needed from unbind() because if dw_hdmi_bind() returns
> > no error then it takes over the job of freeing the encoder (in
> > dw_hdmi_unbind).
> >
> > Signed-off-by: Douglas Anderson <[email protected]>
> > ---
> > Changes in v2:
> > - IMX patch new in v2
> >
> > drivers/gpu/drm/imx/dw_hdmi-imx.c | 11 ++++++++++-
> > 1 file changed, 10 insertions(+), 1 deletion(-)
>
> Mark picked up:
>
> [PATCH v2 1/5] drm/rockchip: dw_hdmi: Call drm_encoder_cleanup() in error path
> [PATCH v2 3/5] drm/rockchip: vop: Fix vop crtc cleanup
> [PATCH v2 4/5] drm/rockchip: dw_hdmi: Don't call platform_set_drvdata()
>
> ...for Rockchip, as you can see at
> <https://patchwork.kernel.org/patch/8523301/>.
>
> Does someone want to pick up:
> [PATCH v2 2/5] drm/imx: dw_hdmi: Call drm_encoder_cleanup() in error path
> [PATCH v2 5/5] drm/imx: dw_hdmi: Don't call platform_set_drvdata()
>
> Thanks!

Thank you for the reminder, both patches applied.

regards
Philipp