diff options
author | Thomas Zimmermann <tzimmermann@suse.de> | 2024-03-25 21:06:55 +0100 |
---|---|---|
committer | Thomas Zimmermann <tzimmermann@suse.de> | 2024-04-02 10:40:50 +0200 |
commit | dfff99cb56904087e35dbecec3d482aa8a95436a (patch) | |
tree | afa318acbee868bcd2bd51c2a8080e2e53de8953 /drivers/gpu/drm/ast | |
parent | 660ed6ba8f62faab67c0d5c615de82e1a65a4d3f (diff) | |
download | linux-dfff99cb56904087e35dbecec3d482aa8a95436a.tar.gz linux-dfff99cb56904087e35dbecec3d482aa8a95436a.tar.bz2 linux-dfff99cb56904087e35dbecec3d482aa8a95436a.zip |
drm/ast: 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: Sui Jingfeng <sui.jingfeng@linux.dev>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Tested-by: Sui Jingfeng <sui.jingfeng@linux.dev>
Link: https://patchwork.freedesktop.org/patch/msgid/20240325200855.21150-11-tzimmermann@suse.de
Diffstat (limited to 'drivers/gpu/drm/ast')
-rw-r--r-- | drivers/gpu/drm/ast/ast_ddc.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/ast/ast_mode.c | 30 |
2 files changed, 28 insertions, 26 deletions
diff --git a/drivers/gpu/drm/ast/ast_ddc.c b/drivers/gpu/drm/ast/ast_ddc.c index b84e656124f1..b7718084422f 100644 --- a/drivers/gpu/drm/ast/ast_ddc.c +++ b/drivers/gpu/drm/ast/ast_ddc.c @@ -59,6 +59,28 @@ static void ast_ddc_algo_bit_data_setscl(void *data, int state) } } +static int ast_ddc_algo_bit_data_pre_xfer(struct i2c_adapter *adapter) +{ + struct ast_ddc *ddc = i2c_get_adapdata(adapter); + struct ast_device *ast = ddc->ast; + + /* + * Protect access to I/O registers from concurrent modesetting + * by acquiring the I/O-register lock. + */ + mutex_lock(&ast->modeset_lock); + + return 0; +} + +static void ast_ddc_algo_bit_data_post_xfer(struct i2c_adapter *adapter) +{ + struct ast_ddc *ddc = i2c_get_adapdata(adapter); + struct ast_device *ast = ddc->ast; + + mutex_unlock(&ast->modeset_lock); +} + static int ast_ddc_algo_bit_data_getsda(void *data) { struct ast_ddc *ddc = data; @@ -137,6 +159,8 @@ struct ast_ddc *ast_ddc_create(struct ast_device *ast) bit->setscl = ast_ddc_algo_bit_data_setscl; bit->getsda = ast_ddc_algo_bit_data_getsda; bit->getscl = ast_ddc_algo_bit_data_getscl; + bit->pre_xfer = ast_ddc_algo_bit_data_pre_xfer; + bit->post_xfer = ast_ddc_algo_bit_data_post_xfer; adapter->algo_data = bit; ret = i2c_bit_add_bus(adapter); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index fc73d3b65b2a..8766a0f2eb3c 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1346,30 +1346,19 @@ static int ast_crtc_init(struct drm_device *dev) static int ast_vga_connector_helper_get_modes(struct drm_connector *connector) { - struct drm_device *dev = connector->dev; - struct ast_device *ast = to_ast_device(dev); struct edid *edid; int count; - /* - * Protect access to I/O registers from concurrent modesetting - * by acquiring the I/O-register lock. - */ - mutex_lock(&ast->modeset_lock); - edid = drm_get_edid(connector, connector->ddc); if (!edid) - goto err_mutex_unlock; - - mutex_unlock(&ast->modeset_lock); + goto err_drm_get_edid; count = drm_add_edid_modes(connector, edid); kfree(edid); return count; -err_mutex_unlock: - mutex_unlock(&ast->modeset_lock); +err_drm_get_edid: drm_connector_update_edid_property(connector, NULL); return 0; } @@ -1444,30 +1433,19 @@ static int ast_vga_output_init(struct ast_device *ast) static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector) { - struct drm_device *dev = connector->dev; - struct ast_device *ast = to_ast_device(dev); struct edid *edid; int count; - /* - * Protect access to I/O registers from concurrent modesetting - * by acquiring the I/O-register lock. - */ - mutex_lock(&ast->modeset_lock); - edid = drm_get_edid(connector, connector->ddc); if (!edid) - goto err_mutex_unlock; - - mutex_unlock(&ast->modeset_lock); + goto err_drm_get_edid; count = drm_add_edid_modes(connector, edid); kfree(edid); return count; -err_mutex_unlock: - mutex_unlock(&ast->modeset_lock); +err_drm_get_edid: drm_connector_update_edid_property(connector, NULL); return 0; } |