Skip to content

Commit dfff99c

Browse files
committed
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
1 parent 660ed6b commit dfff99c

2 files changed

Lines changed: 28 additions & 26 deletions

File tree

drivers/gpu/drm/ast/ast_ddc.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,28 @@ static void ast_ddc_algo_bit_data_setscl(void *data, int state)
5959
}
6060
}
6161

62+
static int ast_ddc_algo_bit_data_pre_xfer(struct i2c_adapter *adapter)
63+
{
64+
struct ast_ddc *ddc = i2c_get_adapdata(adapter);
65+
struct ast_device *ast = ddc->ast;
66+
67+
/*
68+
* Protect access to I/O registers from concurrent modesetting
69+
* by acquiring the I/O-register lock.
70+
*/
71+
mutex_lock(&ast->modeset_lock);
72+
73+
return 0;
74+
}
75+
76+
static void ast_ddc_algo_bit_data_post_xfer(struct i2c_adapter *adapter)
77+
{
78+
struct ast_ddc *ddc = i2c_get_adapdata(adapter);
79+
struct ast_device *ast = ddc->ast;
80+
81+
mutex_unlock(&ast->modeset_lock);
82+
}
83+
6284
static int ast_ddc_algo_bit_data_getsda(void *data)
6385
{
6486
struct ast_ddc *ddc = data;
@@ -137,6 +159,8 @@ struct ast_ddc *ast_ddc_create(struct ast_device *ast)
137159
bit->setscl = ast_ddc_algo_bit_data_setscl;
138160
bit->getsda = ast_ddc_algo_bit_data_getsda;
139161
bit->getscl = ast_ddc_algo_bit_data_getscl;
162+
bit->pre_xfer = ast_ddc_algo_bit_data_pre_xfer;
163+
bit->post_xfer = ast_ddc_algo_bit_data_post_xfer;
140164

141165
adapter->algo_data = bit;
142166
ret = i2c_bit_add_bus(adapter);

drivers/gpu/drm/ast/ast_mode.c

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,30 +1346,19 @@ static int ast_crtc_init(struct drm_device *dev)
13461346

13471347
static int ast_vga_connector_helper_get_modes(struct drm_connector *connector)
13481348
{
1349-
struct drm_device *dev = connector->dev;
1350-
struct ast_device *ast = to_ast_device(dev);
13511349
struct edid *edid;
13521350
int count;
13531351

1354-
/*
1355-
* Protect access to I/O registers from concurrent modesetting
1356-
* by acquiring the I/O-register lock.
1357-
*/
1358-
mutex_lock(&ast->modeset_lock);
1359-
13601352
edid = drm_get_edid(connector, connector->ddc);
13611353
if (!edid)
1362-
goto err_mutex_unlock;
1363-
1364-
mutex_unlock(&ast->modeset_lock);
1354+
goto err_drm_get_edid;
13651355

13661356
count = drm_add_edid_modes(connector, edid);
13671357
kfree(edid);
13681358

13691359
return count;
13701360

1371-
err_mutex_unlock:
1372-
mutex_unlock(&ast->modeset_lock);
1361+
err_drm_get_edid:
13731362
drm_connector_update_edid_property(connector, NULL);
13741363
return 0;
13751364
}
@@ -1444,30 +1433,19 @@ static int ast_vga_output_init(struct ast_device *ast)
14441433

14451434
static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector)
14461435
{
1447-
struct drm_device *dev = connector->dev;
1448-
struct ast_device *ast = to_ast_device(dev);
14491436
struct edid *edid;
14501437
int count;
14511438

1452-
/*
1453-
* Protect access to I/O registers from concurrent modesetting
1454-
* by acquiring the I/O-register lock.
1455-
*/
1456-
mutex_lock(&ast->modeset_lock);
1457-
14581439
edid = drm_get_edid(connector, connector->ddc);
14591440
if (!edid)
1460-
goto err_mutex_unlock;
1461-
1462-
mutex_unlock(&ast->modeset_lock);
1441+
goto err_drm_get_edid;
14631442

14641443
count = drm_add_edid_modes(connector, edid);
14651444
kfree(edid);
14661445

14671446
return count;
14681447

1469-
err_mutex_unlock:
1470-
mutex_unlock(&ast->modeset_lock);
1448+
err_drm_get_edid:
14711449
drm_connector_update_edid_property(connector, NULL);
14721450
return 0;
14731451
}

0 commit comments

Comments
 (0)