Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+24 -9
+24
drivers/gpu/drm/mgag200/mgag200_ddc.c
··· 99 99 return (mga_i2c_read_gpio(ddc->mdev) & ddc->clock) ? 1 : 0; 100 100 } 101 101 102 + static int mgag200_ddc_algo_bit_data_pre_xfer(struct i2c_adapter *adapter) 103 + { 104 + struct mgag200_ddc *ddc = i2c_get_adapdata(adapter); 105 + struct mga_device *mdev = ddc->mdev; 106 + 107 + /* 108 + * Protect access to I/O registers from concurrent modesetting 109 + * by acquiring the I/O-register lock. 110 + */ 111 + mutex_lock(&mdev->rmmio_lock); 112 + 113 + return 0; 114 + } 115 + 116 + static void mgag200_ddc_algo_bit_data_post_xfer(struct i2c_adapter *adapter) 117 + { 118 + struct mgag200_ddc *ddc = i2c_get_adapdata(adapter); 119 + struct mga_device *mdev = ddc->mdev; 120 + 121 + mutex_unlock(&mdev->rmmio_lock); 122 + } 123 + 102 124 static void mgag200_ddc_release(struct drm_device *dev, void *res) 103 125 { 104 126 struct mgag200_ddc *ddc = res; ··· 155 133 bit->setscl = mgag200_ddc_algo_bit_data_setscl; 156 134 bit->getsda = mgag200_ddc_algo_bit_data_getsda; 157 135 bit->getscl = mgag200_ddc_algo_bit_data_getscl; 136 + bit->pre_xfer = mgag200_ddc_algo_bit_data_pre_xfer; 137 + bit->post_xfer = mgag200_ddc_algo_bit_data_post_xfer; 158 138 bit->udelay = 10; 159 139 bit->timeout = usecs_to_jiffies(2200); 160 140
-9
drivers/gpu/drm/mgag200/mgag200_mode.c
··· 743 743 744 744 int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector) 745 745 { 746 - struct mga_device *mdev = to_mga_device(connector->dev); 747 746 const struct drm_edid *drm_edid; 748 747 int count; 749 - 750 - /* 751 - * Protect access to I/O registers from concurrent modesetting 752 - * by acquiring the I/O-register lock. 753 - */ 754 - mutex_lock(&mdev->rmmio_lock); 755 748 756 749 drm_edid = drm_edid_read(connector); 757 750 drm_edid_connector_update(connector, drm_edid); 758 751 count = drm_edid_connector_add_modes(connector); 759 752 drm_edid_free(drm_edid); 760 - 761 - mutex_unlock(&mdev->rmmio_lock); 762 753 763 754 return count; 764 755 }