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

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
......@@ -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);
......
......@@ -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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment