drm/i915: destroy connector sysfs files earlier

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>
This commit is contained in:
Paulo Zanoni 2013-09-26 20:05:59 -03:00 committed by Daniel Vetter
parent 70aff66c95
commit d9255d5714
9 changed files with 10 additions and 9 deletions

View File

@ -677,7 +677,6 @@ intel_crt_detect(struct drm_connector *connector, bool force)
static void intel_crt_destroy(struct drm_connector *connector) static void intel_crt_destroy(struct drm_connector *connector)
{ {
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }

View File

@ -10727,6 +10727,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_connector *connector;
/* /*
* Interrupts and polling as the first thing to avoid creating havoc. * 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 */ /* destroy backlight, if any, before the connectors */
intel_panel_destroy_backlight(dev); 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); drm_mode_config_cleanup(dev);
intel_cleanup_overlay(dev); intel_cleanup_overlay(dev);

View File

@ -3189,7 +3189,6 @@ intel_dp_connector_destroy(struct drm_connector *connector)
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
intel_panel_fini(&intel_connector->panel); intel_panel_fini(&intel_connector->panel);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }

View File

@ -504,7 +504,6 @@ static void intel_dsi_destroy(struct drm_connector *connector)
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
intel_panel_fini(&intel_connector->panel); intel_panel_fini(&intel_connector->panel);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }

View File

@ -367,7 +367,6 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
static void intel_dvo_destroy(struct drm_connector *connector) static void intel_dvo_destroy(struct drm_connector *connector)
{ {
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }

View File

@ -1181,7 +1181,6 @@ static void intel_hdmi_post_disable(struct intel_encoder *encoder)
static void intel_hdmi_destroy(struct drm_connector *connector) static void intel_hdmi_destroy(struct drm_connector *connector)
{ {
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }

View File

@ -474,7 +474,6 @@ static void intel_lvds_destroy(struct drm_connector *connector)
intel_panel_fini(&lvds_connector->base.panel); intel_panel_fini(&lvds_connector->base.panel);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }

View File

@ -2009,7 +2009,6 @@ static void intel_sdvo_destroy(struct drm_connector *connector)
intel_sdvo_connector->tv_format); intel_sdvo_connector->tv_format);
intel_sdvo_destroy_enhance_property(connector); intel_sdvo_destroy_enhance_property(connector);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(intel_sdvo_connector); kfree(intel_sdvo_connector);
} }
@ -2482,6 +2481,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
return true; return true;
err: err:
drm_sysfs_connector_remove(connector);
intel_sdvo_destroy(connector); intel_sdvo_destroy(connector);
return false; return false;
} }
@ -2553,6 +2553,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
return true; return true;
err: err:
drm_sysfs_connector_remove(connector);
intel_sdvo_destroy(connector); intel_sdvo_destroy(connector);
return false; return false;
} }
@ -2624,8 +2625,10 @@ static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo)
list_for_each_entry_safe(connector, tmp, list_for_each_entry_safe(connector, tmp,
&dev->mode_config.connector_list, head) { &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); intel_sdvo_destroy(connector);
}
} }
} }

View File

@ -1433,7 +1433,6 @@ intel_tv_get_modes(struct drm_connector *connector)
static void static void
intel_tv_destroy(struct drm_connector *connector) intel_tv_destroy(struct drm_connector *connector)
{ {
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }