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: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240513125620.6337-10-tzimmermann@suse.de
This commit is contained in:
Thomas Zimmermann
2024-05-13 14:51:14 +02:00
parent b7e04af37e
commit 66d58ec0bc
2 changed files with 24 additions and 9 deletions

View File

@@ -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);

View File

@@ -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;
}