From a6b7ebaadb5c8d869908e803e5616922a5096253 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 5 Sep 2016 20:39:32 +0300 Subject: drm/tilcdc: Take crtc modeset lock while updating the crtc clock rate Take crtc modeset lock while updating the crtc clock rate. To avoid a race in tilcdc_crtc_update_clk(), we do not want crtc mode to change while we update crtc clock. Signed-off-by: Jyri Sarha Reviewed-by: Tomi Valkeinen diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index f8892e9..b1ac61e 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -184,10 +184,13 @@ static int cpufreq_transition(struct notifier_block *nb, { struct tilcdc_drm_private *priv = container_of(nb, struct tilcdc_drm_private, freq_transition); + if (val == CPUFREQ_POSTCHANGE) { if (priv->lcd_fck_rate != clk_get_rate(priv->clk)) { + drm_modeset_lock_crtc(priv->crtc, NULL); priv->lcd_fck_rate = clk_get_rate(priv->clk); tilcdc_crtc_update_clk(priv->crtc); + drm_modeset_unlock_crtc(priv->crtc); } } -- cgit v0.10.2 From 642e51677d29c9f21891b571be4473ec482acaf0 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 6 Sep 2016 16:19:54 +0300 Subject: drm/tilcdc: Clean up LCDC functional clock rate setting code Clean up LCDC functional clock rate setting code. The LCDC functional clock is set by two functions: mode_set_nofb() and cpufreq_transition(). When tilcdc_crtc_mode_set_nofb() is called in atomic commit phase the drm atomic helpers have taken all the necessary drm locks and turned off the crtc, while tilcdc_commit() is keeping LCDC powered on. For mode_set_nofb() just a simple clock setting function without any locking or power management code is enough. The new tilcdc_crtc_set_clk() is implemented for that purpose. cpufreq_transition() on the other hand is called from outside DRM and it needs to take the necessary locks and turn off the CRTC while keeping the LCDC powered. The reimplemented tilcdc_crtc_update_clk() is for that purpose and it uses the new tilcdc_crtc_set_clk() to actually set the clock. Signed-off-by: Jyri Sarha Reviewed-by: Tomi Valkeinen diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 2087689..5579d97 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -35,6 +35,8 @@ struct tilcdc_crtc { bool frame_done; spinlock_t irq_lock; + unsigned int lcd_fck_rate; + ktime_t last_vblank; struct drm_framebuffer *curr_fb; @@ -304,6 +306,37 @@ static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc, return true; } +static void tilcdc_crtc_set_clk(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct tilcdc_drm_private *priv = dev->dev_private; + struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + const unsigned clkdiv = 2; /* using a fixed divider of 2 */ + int ret; + + /* mode.clock is in KHz, set_rate wants parameter in Hz */ + ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv); + if (ret < 0) { + dev_err(dev->dev, "failed to set display clock rate to: %d\n", + crtc->mode.clock); + return; + } + + tilcdc_crtc->lcd_fck_rate = clk_get_rate(priv->clk); + + DBG("lcd_clk=%u, mode clock=%d, div=%u", + tilcdc_crtc->lcd_fck_rate, crtc->mode.clock, clkdiv); + + /* Configure the LCD clock divisor. */ + tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(clkdiv) | + LCDC_RASTER_MODE); + + if (priv->rev == 2) + tilcdc_set(dev, LCDC_CLK_ENABLE_REG, + LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | + LCDC_V2_CORE_CLK_EN); +} + static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); @@ -466,7 +499,7 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) set_scanout(crtc, fb); - tilcdc_crtc_update_clk(crtc); + tilcdc_crtc_set_clk(crtc); crtc->hwmode = crtc->state->adjusted_mode; } @@ -635,41 +668,21 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct tilcdc_drm_private *priv = dev->dev_private; - unsigned long lcd_clk; - const unsigned clkdiv = 2; /* using a fixed divider of 2 */ - int ret; + struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - pm_runtime_get_sync(dev->dev); + drm_modeset_lock_crtc(crtc, NULL); + if (tilcdc_crtc->lcd_fck_rate != clk_get_rate(priv->clk)) { + if (tilcdc_crtc_is_on(crtc)) { + pm_runtime_get_sync(dev->dev); + tilcdc_crtc_disable(crtc); - tilcdc_crtc_disable(crtc); + tilcdc_crtc_set_clk(crtc); - /* mode.clock is in KHz, set_rate wants parameter in Hz */ - ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv); - if (ret < 0) { - dev_err(dev->dev, "failed to set display clock rate to: %d\n", - crtc->mode.clock); - goto out; + tilcdc_crtc_enable(crtc); + pm_runtime_put_sync(dev->dev); + } } - - lcd_clk = clk_get_rate(priv->clk); - - DBG("lcd_clk=%lu, mode clock=%d, div=%u", - lcd_clk, crtc->mode.clock, clkdiv); - - /* Configure the LCD clock divisor. */ - tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(clkdiv) | - LCDC_RASTER_MODE); - - if (priv->rev == 2) - tilcdc_set(dev, LCDC_CLK_ENABLE_REG, - LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | - LCDC_V2_CORE_CLK_EN); - - if (tilcdc_crtc_is_on(crtc)) - tilcdc_crtc_enable(crtc); - -out: - pm_runtime_put_sync(dev->dev); + drm_modeset_unlock_crtc(crtc); } #define SYNC_LOST_COUNT_LIMIT 50 diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index b1ac61e..52ff3e1 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -185,14 +185,8 @@ static int cpufreq_transition(struct notifier_block *nb, struct tilcdc_drm_private *priv = container_of(nb, struct tilcdc_drm_private, freq_transition); - if (val == CPUFREQ_POSTCHANGE) { - if (priv->lcd_fck_rate != clk_get_rate(priv->clk)) { - drm_modeset_lock_crtc(priv->crtc, NULL); - priv->lcd_fck_rate = clk_get_rate(priv->clk); - tilcdc_crtc_update_clk(priv->crtc); - drm_modeset_unlock_crtc(priv->crtc); - } - } + if (val == CPUFREQ_POSTCHANGE) + tilcdc_crtc_update_clk(priv->crtc); return 0; } @@ -286,7 +280,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) } #ifdef CONFIG_CPU_FREQ - priv->lcd_fck_rate = clk_get_rate(priv->clk); priv->freq_transition.notifier_call = cpufreq_transition; ret = cpufreq_register_notifier(&priv->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index a6e5e6d..9780c37 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -74,7 +74,6 @@ struct tilcdc_drm_private { #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; - unsigned int lcd_fck_rate; #endif struct workqueue_struct *wq; -- cgit v0.10.2 From 4e910c7a1860bbc22d06da2f62010ab20a19834f Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 6 Sep 2016 22:55:33 +0300 Subject: drm/tilcdc: Flush flip-work workqueue before drm_flip_work_cleanup() Flush flip-work workqueue before drm_flip_work_cleanup(). It causes a nasty warning if there is unfinished flip-work in the queue when drm_flip_work_cleanup() is called. The flush_workqueue() has to be called before drm_crtc_cleanup() for unref_worker() to be able to do its job. Signed-off-by: Jyri Sarha Reviewed-by: Tomi Valkeinen diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 5579d97..41ce411 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -18,6 +18,7 @@ #include "drm_flip_work.h" #include #include +#include #include "tilcdc_drv.h" #include "tilcdc_regs.h" @@ -227,9 +228,12 @@ static bool tilcdc_crtc_is_on(struct drm_crtc *crtc) static void tilcdc_crtc_destroy(struct drm_crtc *crtc) { struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + struct tilcdc_drm_private *priv = crtc->dev->dev_private; tilcdc_crtc_disable(crtc); + flush_workqueue(priv->wq); + of_node_put(crtc->port); drm_crtc_cleanup(crtc); drm_flip_work_cleanup(&tilcdc_crtc->unref_work); -- cgit v0.10.2 From 7eff0410276374c560e797e7676b7111fed24a3c Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 6 Sep 2016 22:16:27 +0300 Subject: drm/tilcdc: Remove unnecessary tilcdc_crtc_disable() from tilcdc_unload() Remove unnecessary tilcdc_crtc_disable() from tilcdc_unload(). The tilcdc_crtc_disable() called via tilcdc_crtc_destroy() by drm_mode_config_cleanup() couple of lines later. The early call to tilcdc_crtc_disable() was a wrong fix (that worked) for calling drm_flip_work_cleanup() before flushing the flip-work queue. Signed-off-by: Jyri Sarha Reviewed-by: Tomi Valkeinen diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 52ff3e1..1981ae9 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -200,8 +200,6 @@ static int tilcdc_unload(struct drm_device *dev) { struct tilcdc_drm_private *priv = dev->dev_private; - tilcdc_crtc_disable(priv->crtc); - tilcdc_remove_external_encoders(dev); drm_fbdev_cma_fini(priv->fbdev); -- cgit v0.10.2 From 6c94c71400fbb630549611e17b430458c1c00cf8 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Wed, 7 Sep 2016 11:46:40 +0300 Subject: drm/tilcdc: Take CRTC lock when calling tilcdc_crtc_disable() Take CRTC lock when calling tilcdc_crtc_disable() in tilcdc_crtc_destroy(). In theory there could still be some operation ongoing, which should finish before destroying the CRTC. However, the main reason for adding this is to be able to add WARNing in tilcdc_crtc_disable() if CRTC is not locked. Signed-off-by: Jyri Sarha Reviewed-by: Tomi Valkeinen diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 41ce411..c1cbabc 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -230,7 +230,9 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc) struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct tilcdc_drm_private *priv = crtc->dev->dev_private; + drm_modeset_lock_crtc(crtc, NULL); tilcdc_crtc_disable(crtc); + drm_modeset_unlock_crtc(crtc); flush_workqueue(priv->wq); -- cgit v0.10.2 From 2e0965b06d90b9dba76198d026c4c2ee04443aca Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 6 Sep 2016 17:25:08 +0300 Subject: drm/tilcdc: WARN if CRTC is touched without CRTC lock WARN if CRTC is touched without CRTC lock. The crtc functions should not be called simultaneously from multiple threads. Having the DRM CRTC lock should take care of that. Signed-off-by: Jyri Sarha Reviewed-by: Tomi Valkeinen diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index c1cbabc..639821f 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -153,6 +153,8 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + if (tilcdc_crtc->enabled) return; @@ -177,6 +179,8 @@ void tilcdc_crtc_disable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct tilcdc_drm_private *priv = dev->dev_private; + WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + if (!tilcdc_crtc->enabled) return; @@ -249,6 +253,8 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; unsigned long flags; + WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + if (tilcdc_crtc->event) { dev_err(dev->dev, "already pending page flip!\n"); return -EBUSY; @@ -353,6 +359,8 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) struct drm_display_mode *mode = &crtc->state->adjusted_mode; struct drm_framebuffer *fb = crtc->primary->state->fb; + WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + if (WARN_ON(!info)) return; -- cgit v0.10.2 From 0fd86779f04afcddbcff0ecb7ff3b487d17add7c Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Thu, 8 Sep 2016 19:08:56 +0800 Subject: drm/tilcdc: add missing header dependencies We get 4 warnings when building kernel with W=1: drivers/gpu/drm/tilcdc/tilcdc_tfp410.c:393:12: warning: no previous prototype for 'tilcdc_tfp410_init' [-Wmissing-prototypes] drivers/gpu/drm/tilcdc/tilcdc_tfp410.c:398:13: warning: no previous prototype for 'tilcdc_tfp410_fini' [-Wmissing-prototypes] drivers/gpu/drm/tilcdc/tilcdc_panel.c:443:12: warning: no previous prototype for 'tilcdc_panel_init' [-Wmissing-prototypes] drivers/gpu/drm/tilcdc/tilcdc_panel.c:448:13: warning: no previous prototype for 'tilcdc_panel_fini' [-Wmissing-prototypes] In fact, these functions are declared in drivers/gpu/drm/tilcdc/tilcdc_tfp410.h, drivers/gpu/drm/tilcdc/tilcdc_panel.h, so this patch adds missing header dependencies. Signed-off-by: Baoyou Xie Signed-off-by: Jyri Sarha diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 7b36509..2134bb20 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -25,6 +25,7 @@ #include #include "tilcdc_drv.h" +#include "tilcdc_panel.h" struct panel_module { struct tilcdc_module base; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index c6a70da..458043a 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -23,6 +23,7 @@ #include #include "tilcdc_drv.h" +#include "tilcdc_tfp410.h" struct tfp410_module { struct tilcdc_module base; -- cgit v0.10.2 From 952e8faec53ec1de045f44f48a82e5069d2f17b4 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Thu, 8 Sep 2016 19:29:24 +0800 Subject: drm/tilcdc: mark symbols static where possible We get 3 warnings when building kernel with W=1: drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c:142:29: warning: no previous prototype for 'tilcdc_get_overlay' [-Wmissing-prototypes] drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c:198:13: warning: no previous prototype for 'tilcdc_convert_slave_node' [-Wmissing-prototypes] drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c:264:12: warning: no previous prototype for 'tilcdc_slave_compat_init' [-Wmissing-prototypes] In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. So this patch marks these functions with 'static'. Signed-off-by: Baoyou Xie Signed-off-by: Jyri Sarha diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c index f9c79da..dd8de260 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c @@ -139,7 +139,7 @@ static void __init tilcdc_node_disable(struct device_node *node) of_update_property(node, prop); } -struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) +static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) { const int size = __dtb_tilcdc_slave_compat_end - __dtb_tilcdc_slave_compat_begin; @@ -195,7 +195,7 @@ static const char * const tilcdc_slave_props[] __initconst = { NULL }; -void __init tilcdc_convert_slave_node(void) +static void __init tilcdc_convert_slave_node(void) { struct device_node *slave = NULL, *lcdc = NULL; struct device_node *i2c = NULL, *fragment = NULL; @@ -261,7 +261,7 @@ out: of_node_put(fragment); } -int __init tilcdc_slave_compat_init(void) +static int __init tilcdc_slave_compat_init(void) { tilcdc_convert_slave_node(); return 0; -- cgit v0.10.2 From 30457676e2289378094ed67b26ce3bfe312a0246 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 10 Sep 2016 12:32:57 +0000 Subject: drm/tilcdc: Fix non static symbol warning Fixes the following sparse warning: drivers/gpu/drm/tilcdc/tilcdc_drv.c:64:5: warning: symbol 'tilcdc_atomic_check' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Jyri Sarha diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 1981ae9..4b93cab 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -75,8 +75,8 @@ static void tilcdc_fb_output_poll_changed(struct drm_device *dev) drm_fbdev_cma_hotplug_event(priv->fbdev); } -int tilcdc_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) +static int tilcdc_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) { int ret; -- cgit v0.10.2 From 34355ee0d5480f0f437db4d418bd6c494883f708 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 12 Sep 2016 18:45:30 +0300 Subject: drm/tilcdc: Remove "default" from blue-and-red-wiring property binding Remove "default" keyword from blue-and-red-wiring devicetree property binding document. The code does not support and there is no intention to support it. Reported-by: Rob Herring Signed-off-by: Jyri Sarha diff --git a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt index a5007aa..a83abd7 100644 --- a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt +++ b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt @@ -17,9 +17,9 @@ Optional properties: the lcd controller. - max-pixelclock: The maximum pixel clock that can be supported by the lcd controller in KHz. - - blue-and-red-wiring: Recognized values "default", "straight" or - "crossed". This property deals with the LCDC revision 2 (found on - AM335x) color errata [1]. + - blue-and-red-wiring: Recognized values "straight" or "crossed". + This property deals with the LCDC revision 2 (found on AM335x) + color errata [1]. - "straight" indicates normal wiring that supports RGB565, BGR888, and XBGR8888 color formats. - "crossed" indicates wiring that has blue and red wires -- cgit v0.10.2 From cf97ee19629363d5847a4af135cf415f76d7388c Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 22 Sep 2016 09:29:23 +0200 Subject: drm/tilcdc: Return directly after a failed kfree_table_init() in tilcdc_convert_slave_node() Return directly after a memory allocation failed in this function at the beginning. Signed-off-by: Markus Elfring Signed-off-by: Jyri Sarha diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c index dd8de260..623a914 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c @@ -207,7 +207,7 @@ static void __init tilcdc_convert_slave_node(void) int ret; if (kfree_table_init(&kft)) - goto out; + return; lcdc = of_find_matching_node(NULL, tilcdc_of_match); slave = of_find_matching_node(NULL, tilcdc_slave_of_match); -- cgit v0.10.2 From 7b993855dfd5d87e07ac84285d3d9bb0c743dede Mon Sep 17 00:00:00 2001 From: Daniel Schultz Date: Fri, 23 Sep 2016 12:52:49 +0200 Subject: drm/tilcdc: fix wrong error handling When 'component_bind_all' fails it should not try to unbind components in the error handling. This will produce a null pointer kernel panic when no component exist. This patch changes the order of the error handling. Now, it will only unbind components if the are bound. Otherwise, the module will jump to an error label below. Signed-off-by: Daniel Schultz Reviewed-by: Sean Paul Signed-off-by: Jyri Sarha diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 4b93cab..a694977 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -412,13 +412,13 @@ fail_irq_uninstall: fail_vblank_cleanup: drm_vblank_cleanup(dev); -fail_mode_config_cleanup: - drm_mode_config_cleanup(dev); - fail_component_cleanup: if (priv->is_componentized) component_unbind_all(dev->dev, dev); +fail_mode_config_cleanup: + drm_mode_config_cleanup(dev); + fail_external_cleanup: tilcdc_remove_external_encoders(dev); -- cgit v0.10.2