Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f71d0cb authored by Dave Airlie's avatar Dave Airlie
Browse files

drm/dp: add a hw mutex around the transfer functions. (v2)



This should avoid races between connector probing and HPD
irqs in the future, currently mode_config.mutex blocks this
possibility.

Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 885ae1c5
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -216,7 +216,7 @@ i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
 *
 * IMPORTANT:
 * This interface is deprecated, please switch to the new dp aux helpers and
 * drm_dp_aux_register_i2c_bus().
 * drm_dp_aux_register().
 */
int
i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
@@ -382,7 +382,10 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
	 * transactions.
	 */
	for (retry = 0; retry < 7; retry++) {

		mutex_lock(&aux->hw_mutex);
		err = aux->transfer(aux, &msg);
		mutex_unlock(&aux->hw_mutex);
		if (err < 0) {
			if (err == -EBUSY)
				continue;
@@ -596,7 +599,9 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
	 * before giving up the AUX transaction.
	 */
	for (retry = 0; retry < 7; retry++) {
		mutex_lock(&aux->hw_mutex);
		err = aux->transfer(aux, msg);
		mutex_unlock(&aux->hw_mutex);
		if (err < 0) {
			if (err == -EBUSY)
				continue;
@@ -729,13 +734,15 @@ static const struct i2c_algorithm drm_dp_i2c_algo = {
};

/**
 * drm_dp_aux_register_i2c_bus() - register an I2C adapter for I2C-over-AUX
 * drm_dp_aux_register() - initialise and register aux channel
 * @aux: DisplayPort AUX channel
 *
 * Returns 0 on success or a negative error code on failure.
 */
int drm_dp_aux_register_i2c_bus(struct drm_dp_aux *aux)
int drm_dp_aux_register(struct drm_dp_aux *aux)
{
	mutex_init(&aux->hw_mutex);

	aux->ddc.algo = &drm_dp_i2c_algo;
	aux->ddc.algo_data = aux;
	aux->ddc.retries = 3;
@@ -750,14 +757,14 @@ int drm_dp_aux_register_i2c_bus(struct drm_dp_aux *aux)

	return i2c_add_adapter(&aux->ddc);
}
EXPORT_SYMBOL(drm_dp_aux_register_i2c_bus);
EXPORT_SYMBOL(drm_dp_aux_register);

/**
 * drm_dp_aux_unregister_i2c_bus() - unregister an I2C-over-AUX adapter
 * drm_dp_aux_unregister() - unregister an AUX adapter
 * @aux: DisplayPort AUX channel
 */
void drm_dp_aux_unregister_i2c_bus(struct drm_dp_aux *aux)
void drm_dp_aux_unregister(struct drm_dp_aux *aux)
{
	i2c_del_adapter(&aux->ddc);
}
EXPORT_SYMBOL(drm_dp_aux_unregister_i2c_bus);
EXPORT_SYMBOL(drm_dp_aux_unregister);
+5 −5
Original line number Diff line number Diff line
@@ -702,9 +702,9 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
	DRM_DEBUG_KMS("registering %s bus for %s\n", name,
		      connector->base.kdev->kobj.name);

	ret = drm_dp_aux_register_i2c_bus(&intel_dp->aux);
	ret = drm_dp_aux_register(&intel_dp->aux);
	if (ret < 0) {
		DRM_ERROR("drm_dp_aux_register_i2c_bus() for %s failed (%d)\n",
		DRM_ERROR("drm_dp_aux_register() for %s failed (%d)\n",
			  name, ret);
		return;
	}
@@ -714,7 +714,7 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
				intel_dp->aux.ddc.dev.kobj.name);
	if (ret < 0) {
		DRM_ERROR("sysfs_create_link() for %s failed (%d)\n", name, ret);
		drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
		drm_dp_aux_unregister(&intel_dp->aux);
	}
}

@@ -3662,7 +3662,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
	struct intel_dp *intel_dp = &intel_dig_port->dp;
	struct drm_device *dev = intel_dp_to_dev(intel_dp);

	drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
	drm_dp_aux_unregister(&intel_dp->aux);
	drm_encoder_cleanup(encoder);
	if (is_edp(intel_dp)) {
		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
@@ -4244,7 +4244,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
	intel_dp->psr_setup_done = false;

	if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) {
		drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
		drm_dp_aux_unregister(&intel_dp->aux);
		if (is_edp(intel_dp)) {
			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
			mutex_lock(&dev->mode_config.connection_mutex);
+3 −2
Original line number Diff line number Diff line
@@ -222,11 +222,12 @@ void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
	radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd;
	radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev;
	radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer;
	ret = drm_dp_aux_register_i2c_bus(&radeon_connector->ddc_bus->aux);

	ret = drm_dp_aux_register(&radeon_connector->ddc_bus->aux);
	if (!ret)
		radeon_connector->ddc_bus->has_aux = true;

	WARN(ret, "drm_dp_aux_register_i2c_bus() failed with error %d\n", ret);
	WARN(ret, "drm_dp_aux_register() failed with error %d\n", ret);
}

/***** general DP utility functions *****/
+1 −1
Original line number Diff line number Diff line
@@ -988,7 +988,7 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
		return;
	i2c_del_adapter(&i2c->adapter);
	if (i2c->has_aux)
		drm_dp_aux_unregister_i2c_bus(&i2c->aux);
		drm_dp_aux_unregister(&i2c->aux);
	kfree(i2c);
}

+2 −2
Original line number Diff line number Diff line
@@ -332,7 +332,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
	dpaux->aux.transfer = tegra_dpaux_transfer;
	dpaux->aux.dev = &pdev->dev;

	err = drm_dp_aux_register_i2c_bus(&dpaux->aux);
	err = drm_dp_aux_register(&dpaux->aux);
	if (err < 0)
		return err;

@@ -355,7 +355,7 @@ static int tegra_dpaux_remove(struct platform_device *pdev)
{
	struct tegra_dpaux *dpaux = platform_get_drvdata(pdev);

	drm_dp_aux_unregister_i2c_bus(&dpaux->aux);
	drm_dp_aux_unregister(&dpaux->aux);

	mutex_lock(&dpaux_lock);
	list_del(&dpaux->list);
Loading