From: Imre Deak Date: Tue, 11 Feb 2014 15:12:49 +0000 (+0200) Subject: drm/i915: dp: fix order of dp aux i2c device cleanup X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=80f65de3c9b8101c1613fa82df500ba6a099a11c;p=openwrt%2Fstaging%2Fblogic.git drm/i915: dp: fix order of dp aux i2c device cleanup Atm we set the parent of the dp i2c device to be the correspondig connector device. During driver cleanup we first remove the connector device through intel_modeset_cleanup()->drm_sysfs_connector_remove() and only after that the i2c device through the encoder's destroy callback. This order is not supported by the device core and we'll get a warning, see the below bugzilla ticket. The proper order is to remove first any child device and only then the parent device. The first part of the fix changes the i2c device's parent to be the drm device. Its logical owner is not the connector anyway, but the encoder. Since the encoder doesn't have a device object, the next best choice is the drm device. This is the same what we do in the case of the sdvo i2c device and what the nouveau driver does. The second part creates a symlink in the connector's sysfs directory pointing to the i2c device. This is so, that we keep the current ABI, which also makes sense in case someone wants to look up the i2c device belonging to a specific connector. Reference: http://lists.freedesktop.org/archives/intel-gfx/2014-January/038782.html Reference: http://lists.freedesktop.org/archives/intel-gfx/2014-February/039427.html Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70523 Signed-off-by: Imre Deak Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index eeb8e7b42f8a..1ac4b11765c7 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -777,6 +777,16 @@ out: return ret; } +static void +intel_dp_connector_unregister(struct intel_connector *intel_connector) +{ + struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base); + + sysfs_remove_link(&intel_connector->base.kdev->kobj, + intel_dp->adapter.dev.kobj.name); + intel_connector_unregister(intel_connector); +} + static int intel_dp_i2c_init(struct intel_dp *intel_dp, struct intel_connector *intel_connector, const char *name) @@ -794,9 +804,19 @@ intel_dp_i2c_init(struct intel_dp *intel_dp, strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1); intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0'; intel_dp->adapter.algo_data = &intel_dp->algo; - intel_dp->adapter.dev.parent = intel_connector->base.kdev; + intel_dp->adapter.dev.parent = intel_connector->base.dev->dev; ret = i2c_dp_aux_add_bus(&intel_dp->adapter); + if (ret < 0) + return ret; + + ret = sysfs_create_link(&intel_connector->base.kdev->kobj, + &intel_dp->adapter.dev.kobj, + intel_dp->adapter.dev.kobj.name); + + if (ret < 0) + i2c_del_adapter(&intel_dp->adapter); + return ret; } @@ -3799,7 +3819,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_connector->unregister = intel_dp_connector_unregister; intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10; if (HAS_DDI(dev)) {