From: Thomas Zimmermann Date: Mon, 13 May 2024 12:51:14 +0000 (+0200) Subject: drm/mgag200: Acquire I/O-register lock in DDC code X-Git-Tag: io_uring-6.11-20240722~49^2~24^2~107 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=66d58ec0bc659fafcda962a5678dbb3f061d7359;p=linux-block.git 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 Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240513125620.6337-10-tzimmermann@suse.de --- diff --git a/drivers/gpu/drm/mgag200/mgag200_ddc.c b/drivers/gpu/drm/mgag200/mgag200_ddc.c index 3fa11b190943..6d81ea8931e8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_ddc.c +++ b/drivers/gpu/drm/mgag200/mgag200_ddc.c @@ -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); diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index cd1f48b2f998..a04c2b550be0 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -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; }