diff mbox series

[09/10] drm/mgag200: Acquire I/O-register lock in DDC code

Message ID 20240513125620.6337-10-tzimmermann@suse.de (mailing list archive)
State New, archived
Headers show
Series drm/mgag200: Refactor DDC code | expand

Commit Message

Thomas Zimmermann May 13, 2024, 12:51 p.m. UTC
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>
---
 drivers/gpu/drm/mgag200/mgag200_ddc.c  | 24 ++++++++++++++++++++++++
 drivers/gpu/drm/mgag200/mgag200_mode.c |  9 ---------
 2 files changed, 24 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/mgag200/mgag200_ddc.c b/drivers/gpu/drm/mgag200/mgag200_ddc.c
index 3fa11b190943e..6d81ea8931e88 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 cd1f48b2f9986..a04c2b550be02 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;
 }