linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] drm/rockchip: Fix unbind/bind
@ 2020-01-20 17:05 Ezequiel Garcia
  2020-01-20 17:05 ` [PATCH 1/5] component: Add an API to cleanup before unbind Ezequiel Garcia
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Ezequiel Garcia @ 2020-01-20 17:05 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Sandy Huang,
	Heiko Stübner, David Airlie, Daniel Vetter
  Cc: linux-rockchip, linux-arm-kernel, dri-devel, linux-kernel,
	kernel, Ezequiel Garcia

This series is an attempt to fix the unbind/bind crash
(due to an use-after-free bug) found on rockchip-drm driver.

The problem lies in the way the driver uses the component API.
Currently, rockchip_drm_unbind calls component_unbind_all before
drm_mode_config_cleanup, the former releasing the memory
where the DRM objects are embedded.

The series goal is basically to fix all the components,
making proper use of the respective .destroy hooks,
making sure there are no use-after-free or double-free issues.

The first patch is likely the most controversial, which is required
because component_bind_all will call component_unbind without
calling drm_mode_config_cleanup, if any component fails to bind.
As mentioned above, this is problematic in the DRM framework.

Thanks!
Ezequiel

Ezequiel Garcia (5):
  component: Add an API to cleanup before unbind
  drm/rockchip: Fix the device unbind order
  drm/rockchip: vop: Fix CRTC unbind
  drm/rockchip: lvds: Fix component unbind
  drm/rockchip: rk3066_hdmi: Cleanup component unbind

 drivers/base/component.c                    |  9 +++-
 drivers/gpu/drm/rockchip/rk3066_hdmi.c      |  8 +--
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 20 +++++---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 56 ++++++++-------------
 drivers/gpu/drm/rockchip/rockchip_lvds.c    | 20 ++++----
 include/linux/component.h                   | 10 +++-
 6 files changed, 60 insertions(+), 63 deletions(-)

-- 
2.25.0


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

* [PATCH 1/5] component: Add an API to cleanup before unbind
  2020-01-20 17:05 [PATCH 0/5] drm/rockchip: Fix unbind/bind Ezequiel Garcia
@ 2020-01-20 17:05 ` Ezequiel Garcia
  2020-01-20 17:05 ` [PATCH 2/5] drm/rockchip: Fix the device unbind order Ezequiel Garcia
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Ezequiel Garcia @ 2020-01-20 17:05 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Sandy Huang,
	Heiko Stübner, David Airlie, Daniel Vetter
  Cc: linux-rockchip, linux-arm-kernel, dri-devel, linux-kernel,
	kernel, Ezequiel Garcia

Some users of the component API have a special model
for the allocation and release of its resources:
resources are allocated by an API but then
released by other means.

This contrasts with the current component API
assumption: .unbind must undo everything that .bind did.

An example of this is the DRM framework, which expects
registered objects (connectors, planes, CRTCs, etc)
to be released by respective drm_xxx_funcs.destroy hooks.

The drm_xxx_funcs.destroy call is done either directly
by drm_mode_config_cleanup() or in a refcounted fashion,
depending on the type of object.

For example, a DRM CRTC object is registered by
drm_crtc_init_with_planes(), and then released by drm_crtc_cleanup(),
which is normally called from the drm_crtc_funcs.destroy hook.

Now, in this model, drm_mode_config_cleanup() should
always be called before component_unbind() to avoid
use-after-free situations (because each component
has a devres group).

However, component_bind_all() calls component_unbind
on binded components, if any component in the chain
fails to bind.

In order to allow this special case, and following Alan Kay:

  "simple things should be simple, complex things should be possible"

introduce an extension to component_bind_all, which takes an extra
cleanup callback, to be called when binding fails to perform
extra cleanup steps.

This new API allows the following simple pattern:

void unbind_cleanup(...)
{
        drm_mode_config_cleanup(drm_dev);
}

int foo_bind()
{
	component_bind_all_or_cleanup(dev, drm_dev, unbind_cleanup);
}

void foo_unbind()
{
        drm_mode_config_cleanup(drm_dev);
        component_unbind_all(dev, drm_dev);
}

Each DRM component then uses the respective .destroy
hooks to destroy DRM resources, and the .unbind
hooks to release non-DRM resources.

Arguably, this could be viewed as Very Ugly. However, it handles
this complex case, making it possible to fix the current
unbind crashes that some DRM drivers suffer from,
in a non-invasive way, keeping the DRM resource handling model.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/base/component.c  |  9 +++++++--
 include/linux/component.h | 10 +++++++++-
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c
index 532a3a5d8f63..371cff9208cf 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -622,12 +622,14 @@ static int component_bind(struct component *component, struct master *master,
  * component_bind_all - bind all components of an aggregate driver
  * @master_dev: device with the aggregate driver
  * @data: opaque pointer, passed to all components
+ * @cleanup: optional cleanup callback.
  *
  * Binds all components of the aggregate @dev by passing @data to their
  * &component_ops.bind functions. Should be called from
  * &component_master_ops.bind.
  */
-int component_bind_all(struct device *master_dev, void *data)
+int component_bind_all_or_cleanup(struct device *master_dev,
+				  void *data, void (*cleanup)(void *data))
 {
 	struct master *master;
 	struct component *c;
@@ -650,6 +652,9 @@ int component_bind_all(struct device *master_dev, void *data)
 		}
 
 	if (ret != 0) {
+		if (cleanup)
+			cleanup(data);
+
 		for (; i > 0; i--)
 			if (!master->match->compare[i - 1].duplicate) {
 				c = master->match->compare[i - 1].component;
@@ -659,7 +664,7 @@ int component_bind_all(struct device *master_dev, void *data)
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(component_bind_all);
+EXPORT_SYMBOL_GPL(component_bind_all_or_cleanup);
 
 static int __component_add(struct device *dev, const struct component_ops *ops,
 	int subcomponent)
diff --git a/include/linux/component.h b/include/linux/component.h
index 16de18f473d7..1a5c7b772de3 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -38,7 +38,15 @@ int component_add_typed(struct device *dev, const struct component_ops *ops,
 	int subcomponent);
 void component_del(struct device *, const struct component_ops *);
 
-int component_bind_all(struct device *master, void *master_data);
+int component_bind_all_or_cleanup(struct device *master,
+				  void *master_data,
+				  void (*cleanup)(void *data));
+
+static inline int component_bind_all(struct device *master, void *master_data)
+{
+	return component_bind_all_or_cleanup(master, master_data, NULL);
+}
+
 void component_unbind_all(struct device *master, void *master_data);
 
 struct master;
-- 
2.25.0


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

* [PATCH 2/5] drm/rockchip: Fix the device unbind order
  2020-01-20 17:05 [PATCH 0/5] drm/rockchip: Fix unbind/bind Ezequiel Garcia
  2020-01-20 17:05 ` [PATCH 1/5] component: Add an API to cleanup before unbind Ezequiel Garcia
@ 2020-01-20 17:05 ` Ezequiel Garcia
  2020-01-20 17:06 ` [PATCH 3/5] drm/rockchip: vop: Fix CRTC unbind Ezequiel Garcia
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Ezequiel Garcia @ 2020-01-20 17:05 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Sandy Huang,
	Heiko Stübner, David Airlie, Daniel Vetter
  Cc: linux-rockchip, linux-arm-kernel, dri-devel, linux-kernel,
	kernel, Ezequiel Garcia

In order to cleanup the configuration, destroying the components
in the pipeline, the components must be present.

Therefore, cleanup the config first, and unbind the components
later.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 20ecb1508a22..ca12a35483f9 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -108,6 +108,11 @@ static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
 	iommu_domain_free(private->domain);
 }
 
+static void unbind_cleanup(void *data)
+{
+	drm_mode_config_cleanup((struct drm_device *)data);
+}
+
 static int rockchip_drm_bind(struct device *dev)
 {
 	struct drm_device *drm_dev;
@@ -140,13 +145,13 @@ static int rockchip_drm_bind(struct device *dev)
 	rockchip_drm_mode_config_init(drm_dev);
 
 	/* Try to bind all sub drivers. */
-	ret = component_bind_all(dev, drm_dev);
+	ret = component_bind_all_or_cleanup(dev, drm_dev, unbind_cleanup);
 	if (ret)
-		goto err_mode_config_cleanup;
+		goto err_free;
 
 	ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
 	if (ret)
-		goto err_unbind_all;
+		goto err_drm_cleanup;
 
 	drm_mode_config_reset(drm_dev);
 
@@ -158,7 +163,7 @@ static int rockchip_drm_bind(struct device *dev)
 
 	ret = rockchip_drm_fbdev_init(drm_dev);
 	if (ret)
-		goto err_unbind_all;
+		goto err_drm_cleanup;
 
 	/* init kms poll for handling hpd */
 	drm_kms_helper_poll_init(drm_dev);
@@ -171,10 +176,9 @@ static int rockchip_drm_bind(struct device *dev)
 err_kms_helper_poll_fini:
 	drm_kms_helper_poll_fini(drm_dev);
 	rockchip_drm_fbdev_fini(drm_dev);
-err_unbind_all:
-	component_unbind_all(dev, drm_dev);
-err_mode_config_cleanup:
+err_drm_cleanup:
 	drm_mode_config_cleanup(drm_dev);
+	component_unbind_all(dev, drm_dev);
 	rockchip_iommu_cleanup(drm_dev);
 err_free:
 	drm_dev->dev_private = NULL;
@@ -193,8 +197,8 @@ static void rockchip_drm_unbind(struct device *dev)
 	drm_kms_helper_poll_fini(drm_dev);
 
 	drm_atomic_helper_shutdown(drm_dev);
-	component_unbind_all(dev, drm_dev);
 	drm_mode_config_cleanup(drm_dev);
+	component_unbind_all(dev, drm_dev);
 	rockchip_iommu_cleanup(drm_dev);
 
 	drm_dev->dev_private = NULL;
-- 
2.25.0


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

* [PATCH 3/5] drm/rockchip: vop: Fix CRTC unbind
  2020-01-20 17:05 [PATCH 0/5] drm/rockchip: Fix unbind/bind Ezequiel Garcia
  2020-01-20 17:05 ` [PATCH 1/5] component: Add an API to cleanup before unbind Ezequiel Garcia
  2020-01-20 17:05 ` [PATCH 2/5] drm/rockchip: Fix the device unbind order Ezequiel Garcia
@ 2020-01-20 17:06 ` Ezequiel Garcia
  2020-01-20 17:06 ` [PATCH 4/5] drm/rockchip: lvds: Fix component unbind Ezequiel Garcia
  2020-01-20 17:06 ` [PATCH 5/5] drm/rockchip: rk3066_hdmi: Cleanup " Ezequiel Garcia
  4 siblings, 0 replies; 6+ messages in thread
From: Ezequiel Garcia @ 2020-01-20 17:06 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Sandy Huang,
	Heiko Stübner, David Airlie, Daniel Vetter
  Cc: linux-rockchip, linux-arm-kernel, dri-devel, linux-kernel,
	kernel, Ezequiel Garcia

In order to fix device unbinding, the CRTC release path needs to
be fixed. Get rid of the use-after-free issue that arise
for calling drm_crtc_cleanup() prematurely, by moving
all the CRTC resource release to the crtc.destroy() hook.

The vop_unbind() function is only responsible for the release
of driver-specific (i.e. vop-specific) resources.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 56 ++++++++-------------
 1 file changed, 20 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index d04b3492bdac..87c43097da7e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1387,6 +1387,11 @@ static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
 
 static void vop_crtc_destroy(struct drm_crtc *crtc)
 {
+	struct vop *vop = to_vop(crtc);
+
+	drm_flip_work_cleanup(&vop->fb_unref_work);
+	drm_self_refresh_helper_cleanup(crtc);
+	of_node_put(crtc->port);
 	drm_crtc_cleanup(crtc);
 }
 
@@ -1606,12 +1611,22 @@ static void vop_plane_add_properties(struct drm_plane *plane,
 						   DRM_MODE_ROTATE_0 | flags);
 }
 
+static void vop_plane_cleanup(struct vop *vop)
+{
+	struct drm_device *drm_dev = vop->drm_dev;
+	struct drm_plane *plane, *tmp;
+
+	list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
+				 head)
+		drm_plane_cleanup(plane);
+}
+
 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, *tmp;
+	struct drm_plane *primary = NULL, *cursor = NULL;
 	struct drm_crtc *crtc = &vop->crtc;
 	struct device_node *port;
 	int ret;
@@ -1625,6 +1640,7 @@ static int vop_create_crtc(struct vop *vop)
 	for (i = 0; i < vop_data->win_size; i++) {
 		struct vop_win *vop_win = &vop->win[i];
 		const struct vop_win_data *win_data = vop_win->data;
+		struct drm_plane *plane;
 
 		if (win_data->type != DRM_PLANE_TYPE_PRIMARY &&
 		    win_data->type != DRM_PLANE_TYPE_CURSOR)
@@ -1714,42 +1730,10 @@ static int vop_create_crtc(struct vop *vop)
 err_cleanup_crtc:
 	drm_crtc_cleanup(crtc);
 err_cleanup_planes:
-	list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
-				 head)
-		drm_plane_cleanup(plane);
+	vop_plane_cleanup(vop);
 	return ret;
 }
 
-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;
-
-	drm_self_refresh_helper_cleanup(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);
-	drm_flip_work_cleanup(&vop->fb_unref_work);
-}
-
 static int vop_initial(struct vop *vop)
 {
 	struct reset_control *ahb_rst;
@@ -2020,7 +2004,8 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
 
 err_disable_pm_runtime:
 	pm_runtime_disable(&pdev->dev);
-	vop_destroy_crtc(vop);
+	vop_plane_cleanup(vop);
+	vop_crtc_destroy(&vop->crtc);
 	return ret;
 }
 
@@ -2032,7 +2017,6 @@ static void vop_unbind(struct device *dev, struct device *master, void *data)
 		rockchip_rgb_fini(vop->rgb);
 
 	pm_runtime_disable(dev);
-	vop_destroy_crtc(vop);
 
 	clk_unprepare(vop->aclk);
 	clk_unprepare(vop->hclk);
-- 
2.25.0


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

* [PATCH 4/5] drm/rockchip: lvds: Fix component unbind
  2020-01-20 17:05 [PATCH 0/5] drm/rockchip: Fix unbind/bind Ezequiel Garcia
                   ` (2 preceding siblings ...)
  2020-01-20 17:06 ` [PATCH 3/5] drm/rockchip: vop: Fix CRTC unbind Ezequiel Garcia
@ 2020-01-20 17:06 ` Ezequiel Garcia
  2020-01-20 17:06 ` [PATCH 5/5] drm/rockchip: rk3066_hdmi: Cleanup " Ezequiel Garcia
  4 siblings, 0 replies; 6+ messages in thread
From: Ezequiel Garcia @ 2020-01-20 17:06 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Sandy Huang,
	Heiko Stübner, David Airlie, Daniel Vetter
  Cc: linux-rockchip, linux-arm-kernel, dri-devel, linux-kernel,
	kernel, Ezequiel Garcia

Remove the explicit encoder disable: it's
already part of the CRTC shutdown, in both
atomic and legacy API cases.

Also, encoder and connector cleanup is performed
by the DRM .destroy hooks, for encoder and connector
respectively. It can be removed as well.

Finally, move the panel detach call to the connector
.destroy hook, where it belongs.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/gpu/drm/rockchip/rockchip_lvds.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index f25a36743cbd..154f14a317d7 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -100,9 +100,18 @@ static inline int rockchip_lvds_name_to_output(const char *s)
 	return -EINVAL;
 }
 
+static void
+rockchip_lvds_connector_destroy(struct drm_connector *connector)
+{
+	struct rockchip_lvds *lvds = connector_to_lvds(connector);
+
+	drm_panel_detach(lvds->panel);
+	drm_connector_cleanup(connector);
+}
+
 static const struct drm_connector_funcs rockchip_lvds_connector_funcs = {
 	.fill_modes = drm_helper_probe_single_connector_modes,
-	.destroy = drm_connector_cleanup,
+	.destroy = rockchip_lvds_connector_destroy,
 	.reset = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
@@ -675,16 +684,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 static void rockchip_lvds_unbind(struct device *dev, struct device *master,
 				void *data)
 {
-	struct rockchip_lvds *lvds = dev_get_drvdata(dev);
-	const struct drm_encoder_helper_funcs *encoder_funcs;
-
-	encoder_funcs = lvds->soc_data->helper_funcs;
-	encoder_funcs->disable(&lvds->encoder);
-	if (lvds->panel)
-		drm_panel_detach(lvds->panel);
 	pm_runtime_disable(dev);
-	drm_connector_cleanup(&lvds->connector);
-	drm_encoder_cleanup(&lvds->encoder);
 }
 
 static const struct component_ops rockchip_lvds_component_ops = {
-- 
2.25.0


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

* [PATCH 5/5] drm/rockchip: rk3066_hdmi: Cleanup component unbind
  2020-01-20 17:05 [PATCH 0/5] drm/rockchip: Fix unbind/bind Ezequiel Garcia
                   ` (3 preceding siblings ...)
  2020-01-20 17:06 ` [PATCH 4/5] drm/rockchip: lvds: Fix component unbind Ezequiel Garcia
@ 2020-01-20 17:06 ` Ezequiel Garcia
  4 siblings, 0 replies; 6+ messages in thread
From: Ezequiel Garcia @ 2020-01-20 17:06 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Sandy Huang,
	Heiko Stübner, David Airlie, Daniel Vetter
  Cc: linux-rockchip, linux-arm-kernel, dri-devel, linux-kernel,
	kernel, Ezequiel Garcia

Remove drm_connector_unregister() since it should be
used only by drivers that call drm_dev_register
explicitly.

Also, call the DRM cleanups directly, instead of
(ab)using the destroy hooks, for readability reasons.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/gpu/drm/rockchip/rk3066_hdmi.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c
index fe203d38664e..5a2d62a2cf50 100644
--- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c
+++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c
@@ -518,7 +518,6 @@ rk3066_hdmi_probe_single_connector_modes(struct drm_connector *connector,
 
 static void rk3066_hdmi_connector_destroy(struct drm_connector *connector)
 {
-	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 }
 
@@ -819,8 +818,8 @@ static int rk3066_hdmi_bind(struct device *dev, struct device *master,
 	return 0;
 
 err_cleanup_hdmi:
-	hdmi->connector.funcs->destroy(&hdmi->connector);
-	hdmi->encoder.funcs->destroy(&hdmi->encoder);
+	drm_connector_cleanup(&hdmi->connector);
+	drm_encoder_cleanup(&hdmi->encoder);
 err_disable_i2c:
 	i2c_put_adapter(hdmi->ddc);
 err_disable_hclk:
@@ -834,9 +833,6 @@ static void rk3066_hdmi_unbind(struct device *dev, struct device *master,
 {
 	struct rk3066_hdmi *hdmi = dev_get_drvdata(dev);
 
-	hdmi->connector.funcs->destroy(&hdmi->connector);
-	hdmi->encoder.funcs->destroy(&hdmi->encoder);
-
 	i2c_put_adapter(hdmi->ddc);
 	clk_disable_unprepare(hdmi->hclk);
 }
-- 
2.25.0


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

end of thread, other threads:[~2020-01-20 17:06 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-20 17:05 [PATCH 0/5] drm/rockchip: Fix unbind/bind Ezequiel Garcia
2020-01-20 17:05 ` [PATCH 1/5] component: Add an API to cleanup before unbind Ezequiel Garcia
2020-01-20 17:05 ` [PATCH 2/5] drm/rockchip: Fix the device unbind order Ezequiel Garcia
2020-01-20 17:06 ` [PATCH 3/5] drm/rockchip: vop: Fix CRTC unbind Ezequiel Garcia
2020-01-20 17:06 ` [PATCH 4/5] drm/rockchip: lvds: Fix component unbind Ezequiel Garcia
2020-01-20 17:06 ` [PATCH 5/5] drm/rockchip: rk3066_hdmi: Cleanup " Ezequiel Garcia

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).