]> git.karo-electronics.de Git - linux-beck.git/commitdiff
drm/i915: destroy connector sysfs files earlier
authorPaulo Zanoni <paulo.r.zanoni@intel.com>
Thu, 26 Sep 2013 23:05:59 +0000 (20:05 -0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 1 Oct 2013 05:45:48 +0000 (07:45 +0200)
For some reason, every single time I try to run module_reload
something tries to read the connector sysfs files. This happens
after we destroy the encoders and before we destroy the connectors, so
when the sysfs read triggers the connector detect() function,
intel_conector->encoder points to memory that was already freed.

The bad backtrace is just:
    [<ffffffff8163ca9a>] dump_stack+0x54/0x74
    [<ffffffffa00c2c8e>] intel_dp_detect+0x1e/0x4b0 [i915]
    [<ffffffffa001913d>] status_show+0x3d/0x80 [drm]
    [<ffffffff813d5340>] dev_attr_show+0x20/0x60
    [<ffffffff81221f50>] ? sysfs_read_file+0x80/0x1b0
    [<ffffffff81221f79>] sysfs_read_file+0xa9/0x1b0
    [<ffffffff811aaf1e>] vfs_read+0x9e/0x170
    [<ffffffff811aba4c>] SyS_read+0x4c/0xa0
    [<ffffffff8164e392>] system_call_fastpath+0x16/0x1b

But if you add tons of memory checking debug options to your Kernel
you'll also see:
 - general protection fault: 0000
 - BUG kmalloc-4096 (Tainted: G      D W   ): Poison overwritten
 - INFO: Allocated in intel_ddi_init+0x65/0x270 [i915]
 - INFO: Freed in intel_dp_encoder_destroy+0x69/0xb0 [i915]
Among a bunch of other error messages.

So this commit just destroys the sysfs files before both the encoder
and connectors are freed.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c

index 0263629332d02529d9ff37420aac6bd997d77acc..942b9acb0d8eefa6f67edcd7a560e5932f643be3 100644 (file)
@@ -677,7 +677,6 @@ intel_crt_detect(struct drm_connector *connector, bool force)
 
 static void intel_crt_destroy(struct drm_connector *connector)
 {
-       drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
        kfree(connector);
 }
index 76870f0ffa7a2b4574de5f57a1053ad8b0c60704..29b9387798122c11cffdd81631039028f2d26a2e 100644 (file)
@@ -10727,6 +10727,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc;
+       struct drm_connector *connector;
 
        /*
         * Interrupts and polling as the first thing to avoid creating havoc.
@@ -10769,6 +10770,10 @@ void intel_modeset_cleanup(struct drm_device *dev)
        /* destroy backlight, if any, before the connectors */
        intel_panel_destroy_backlight(dev);
 
+       /* destroy the sysfs files before encoders/connectors */
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+               drm_sysfs_connector_remove(connector);
+
        drm_mode_config_cleanup(dev);
 
        intel_cleanup_overlay(dev);
index 2d790d019725d38f86220ca8901e16862a775a28..5614365465c900d3b7f0e51d93a063a155c8626f 100644 (file)
@@ -3189,7 +3189,6 @@ intel_dp_connector_destroy(struct drm_connector *connector)
        if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
                intel_panel_fini(&intel_connector->panel);
 
-       drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
        kfree(connector);
 }
index 674fd4989b457f62e5ef0922ae5243b0557cbe7e..9a2fdd2a7e3450645e35c9e50fff7dd9aa4cec30 100644 (file)
@@ -504,7 +504,6 @@ static void intel_dsi_destroy(struct drm_connector *connector)
 
        DRM_DEBUG_KMS("\n");
        intel_panel_fini(&intel_connector->panel);
-       drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
        kfree(connector);
 }
index 91287d1d30591e8533f7585e766af1067e70635e..1b64145c669aab596aac1f1c6cf6b9bb875553d3 100644 (file)
@@ -367,7 +367,6 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
 
 static void intel_dvo_destroy(struct drm_connector *connector)
 {
-       drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
        kfree(connector);
 }
index 6004f9c549aaeb05de5e04dff6b44acc69f5f56c..4f4d346db8f048450fcadcb0ae72050f15175b80 100644 (file)
@@ -1181,7 +1181,6 @@ static void intel_hdmi_post_disable(struct intel_encoder *encoder)
 
 static void intel_hdmi_destroy(struct drm_connector *connector)
 {
-       drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
        kfree(connector);
 }
index fb3f8efcc6e2e00639465e6d96a8818d92fddfe6..ae0c843dd2630cfad8b8538928de4fe65fd50509 100644 (file)
@@ -474,7 +474,6 @@ static void intel_lvds_destroy(struct drm_connector *connector)
 
        intel_panel_fini(&lvds_connector->base.panel);
 
-       drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
        kfree(connector);
 }
index 5e59d64cfd95435c43f901a9d625c18fbf8dcf96..a583e8f718a7f0f4b87b4fe724336c73ad1a8198 100644 (file)
@@ -2009,7 +2009,6 @@ static void intel_sdvo_destroy(struct drm_connector *connector)
                                     intel_sdvo_connector->tv_format);
 
        intel_sdvo_destroy_enhance_property(connector);
-       drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
        kfree(intel_sdvo_connector);
 }
@@ -2482,6 +2481,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
        return true;
 
 err:
+       drm_sysfs_connector_remove(connector);
        intel_sdvo_destroy(connector);
        return false;
 }
@@ -2553,6 +2553,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
        return true;
 
 err:
+       drm_sysfs_connector_remove(connector);
        intel_sdvo_destroy(connector);
        return false;
 }
@@ -2624,8 +2625,10 @@ static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo)
 
        list_for_each_entry_safe(connector, tmp,
                                 &dev->mode_config.connector_list, head) {
-               if (intel_attached_encoder(connector) == &intel_sdvo->base)
+               if (intel_attached_encoder(connector) == &intel_sdvo->base) {
+                       drm_sysfs_connector_remove(connector);
                        intel_sdvo_destroy(connector);
+               }
        }
 }
 
index 75925a1ab351cc78a88b52ccb31ada27fdbe4608..92895f92a738720e7704bde70046d7f43f0a7adc 100644 (file)
@@ -1433,7 +1433,6 @@ intel_tv_get_modes(struct drm_connector *connector)
 static void
 intel_tv_destroy(struct drm_connector *connector)
 {
-       drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
        kfree(connector);
 }