Commit 66d58ec0 authored by Thomas Zimmermann's avatar Thomas Zimmermann
Browse files

drm/mgag200: Acquire I/O-register lock in DDC code



The modeset lock protects the DDC code from concurrent modeset
operations, which use the same registers. Move that code from the
connector helpers into the DDC helpers .pre_xfer() and .post_xfer().

Both, .pre_xfer() and .post_xfer(), enclose the transfer of data blocks
over the I2C channel in the internal I2C function bit_xfer(). Both
calls are executed unconditionally if present. Invoking DDC transfers
from any where within the driver now takes the lock.

Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarJocelyn Falempe <jfalempe@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240513125620.6337-10-tzimmermann@suse.de
parent b7e04af3
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -99,6 +99,28 @@ static int mgag200_ddc_algo_bit_data_getscl(void *data)
	return (mga_i2c_read_gpio(ddc->mdev) & ddc->clock) ? 1 : 0;
}

static int mgag200_ddc_algo_bit_data_pre_xfer(struct i2c_adapter *adapter)
{
	struct mgag200_ddc *ddc = i2c_get_adapdata(adapter);
	struct mga_device *mdev = ddc->mdev;

	/*
	 * Protect access to I/O registers from concurrent modesetting
	 * by acquiring the I/O-register lock.
	 */
	mutex_lock(&mdev->rmmio_lock);

	return 0;
}

static void mgag200_ddc_algo_bit_data_post_xfer(struct i2c_adapter *adapter)
{
	struct mgag200_ddc *ddc = i2c_get_adapdata(adapter);
	struct mga_device *mdev = ddc->mdev;

	mutex_unlock(&mdev->rmmio_lock);
}

static void mgag200_ddc_release(struct drm_device *dev, void *res)
{
	struct mgag200_ddc *ddc = res;
@@ -133,6 +155,8 @@ struct i2c_adapter *mgag200_ddc_create(struct mga_device *mdev)
	bit->setscl = mgag200_ddc_algo_bit_data_setscl;
	bit->getsda = mgag200_ddc_algo_bit_data_getsda;
	bit->getscl = mgag200_ddc_algo_bit_data_getscl;
	bit->pre_xfer = mgag200_ddc_algo_bit_data_pre_xfer;
	bit->post_xfer = mgag200_ddc_algo_bit_data_post_xfer;
	bit->udelay = 10;
	bit->timeout = usecs_to_jiffies(2200);

+0 −9
Original line number Diff line number Diff line
@@ -743,23 +743,14 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st

int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector)
{
	struct mga_device *mdev = to_mga_device(connector->dev);
	const struct drm_edid *drm_edid;
	int count;

	/*
	 * Protect access to I/O registers from concurrent modesetting
	 * by acquiring the I/O-register lock.
	 */
	mutex_lock(&mdev->rmmio_lock);

	drm_edid = drm_edid_read(connector);
	drm_edid_connector_update(connector, drm_edid);
	count = drm_edid_connector_add_modes(connector);
	drm_edid_free(drm_edid);

	mutex_unlock(&mdev->rmmio_lock);

	return count;
}