drm/i915: add unregister callback to connector
authorImre Deak <imre.deak@intel.com>
Tue, 11 Feb 2014 15:12:48 +0000 (17:12 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 11 Jun 2014 18:54:14 +0000 (11:54 -0700)
commit 4932e2c3c716067f3580e1a9687bed9d751549e3 upstream.

Since

commit d9255d57147e1dbcebdf6670409c2fa0ac3609e6
Author: Paulo Zanoni <paulo.r.zanoni@intel.com>
Date:   Thu Sep 26 20:05:59 2013 -0300

it became clear that we need to separate the unload sequence into two
parts:

1. remove all interfaces through which new operations on some object
   (crtc, encoder, connector) can be started and make sure all pending
   operations are completed
2. do the actual tear down of the internal representation of the above
   objects

The above commit achieved this separation for connectors by splitting
out the sysfs removal part from the connector's destroy callback and
doing this removal before calling drm_mode_config_cleanup() which does
the actual tear-down of all the drm objects.

Since we'll have to customize the interface removal part for different
types of connectors in the upcoming patches, add a new unregister
callback and move the interface removal part to it.

No functional change.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Antti Koskipää <antti.koskipaa@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpu/drm/i915/i915_drv.h
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_drv.h
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 697f2150a997b9e092b7f3eecd571694b3cae46b..4677af964df7b75ffe811f96a7162b7a388a5433 100644 (file)
@@ -2426,6 +2426,7 @@ extern void intel_modeset_suspend_hw(struct drm_device *dev);
 extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
+extern void intel_connector_unregister(struct intel_connector *);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
 extern void intel_modeset_setup_hw_state(struct drm_device *dev,
                                         bool force_restore);
index a60a755f9977e448eb502b4905dc47d64ec20529..b19ddacbe19ddfa321bdbd9e7a9e9fcef1fe3270 100644 (file)
@@ -841,6 +841,7 @@ void intel_crt_init(struct drm_device *dev)
                crt->base.get_hw_state = intel_crt_get_hw_state;
        }
        intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
index 9d4d837506d01513bc732e123f599f2aaff77190..b6fb3ebe553a597421f6a0fb0c3c486aa1a6e329 100644 (file)
@@ -11368,6 +11368,14 @@ void intel_modeset_gem_init(struct drm_device *dev)
        mutex_unlock(&dev->mode_config.mutex);
 }
 
+void intel_connector_unregister(struct intel_connector *intel_connector)
+{
+       struct drm_connector *connector = &intel_connector->base;
+
+       intel_panel_destroy_backlight(connector);
+       drm_sysfs_connector_remove(connector);
+}
+
 void intel_modeset_cleanup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -11412,8 +11420,10 @@ void intel_modeset_cleanup(struct drm_device *dev)
 
        /* destroy the backlight and sysfs files before encoders/connectors */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               intel_panel_destroy_backlight(connector);
-               drm_sysfs_connector_remove(connector);
+               struct intel_connector *intel_connector;
+
+               intel_connector = to_intel_connector(connector);
+               intel_connector->unregister(intel_connector);
        }
 
        drm_mode_config_cleanup(dev);
index 2688f6d64bb9f3e6883e5a8a9216a38fd794d880..b105e20388c8deb127feb356dfe839f4f72eecd3 100644 (file)
@@ -3686,6 +3686,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
        else
                intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
        if (HAS_DDI(dev)) {
index 00de120531ace4a06cfbc38f6c47609d660c8dee..0b59914344e4e9370eb8647b83ce101c25d5237f 100644 (file)
@@ -187,6 +187,14 @@ struct intel_connector {
         * and active (i.e. dpms ON state). */
        bool (*get_hw_state)(struct intel_connector *);
 
+       /*
+        * Removes all interfaces through which the connector is accessible
+        * - like sysfs, debugfs entries -, so that no new operations can be
+        * started on the connector. Also makes sure all currently pending
+        * operations finish before returing.
+        */
+       void (*unregister)(struct intel_connector *);
+
        /* Panel info for eDP and LVDS */
        struct intel_panel panel;
 
index fabbf0d895cf2a5e133d804d5e8e05f0f26f79ad..ad05683ac5b6fe3c2a52f5370593ef5036f0dba7 100644 (file)
@@ -586,6 +586,7 @@ bool intel_dsi_init(struct drm_device *dev)
        intel_encoder->get_config = intel_dsi_get_config;
 
        intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        for (i = 0; i < ARRAY_SIZE(intel_dsi_devices); i++) {
                dsi = &intel_dsi_devices[i];
index eeff998e52efdea93534ffb680582503f9f2a56c..86eeb8b7d435835e722afe86867c8a80890cad9e 100644 (file)
@@ -477,6 +477,7 @@ void intel_dvo_init(struct drm_device *dev)
        intel_encoder->compute_config = intel_dvo_compute_config;
        intel_encoder->mode_set = intel_dvo_mode_set;
        intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        /* Now, try to find a controller */
        for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
index ca5d23d17d209e1502d80ec0ce8b4989e91ac615..7b277c369dceb86f6cabaf161990c00627640ef4 100644 (file)
@@ -1262,6 +1262,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
                intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
        else
                intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        intel_hdmi_add_properties(intel_hdmi, connector);
 
index 8bcb93a2a9f6b1d09780c3154f6c656895451e8e..eb8f64b5fb85197ff4dce413e195b26e33a4e1a6 100644 (file)
@@ -957,6 +957,7 @@ void intel_lvds_init(struct drm_device *dev)
        intel_encoder->get_hw_state = intel_lvds_get_hw_state;
        intel_encoder->get_config = intel_lvds_get_config;
        intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        intel_connector_attach_encoder(intel_connector, intel_encoder);
        intel_encoder->type = INTEL_OUTPUT_LVDS;
index 95bdfb3c431c8467b105c616f6d5f9567505804f..cbc2feeda59df91dc790d44b8ef78a807ce6ee15 100644 (file)
@@ -2397,6 +2397,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
        connector->base.base.doublescan_allowed = 0;
        connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
        connector->base.get_hw_state = intel_sdvo_connector_get_hw_state;
+       connector->base.unregister = intel_connector_unregister;
 
        intel_connector_attach_encoder(&connector->base, &encoder->base);
        drm_sysfs_connector_add(&connector->base.base);
index 99faac555d3b72820f876cffa3e2011926887538..365c7c47c46c2aa85e86675a0075e13c09208243 100644 (file)
@@ -1639,6 +1639,7 @@ intel_tv_init(struct drm_device *dev)
        intel_encoder->disable = intel_disable_tv;
        intel_encoder->get_hw_state = intel_tv_get_hw_state;
        intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        intel_connector_attach_encoder(intel_connector, intel_encoder);
        intel_encoder->type = INTEL_OUTPUT_TVOUT;