Commit b89e5ff9 authored by Deepak Rawat's avatar Deepak Rawat Committed by Thomas Hellstrom

drm/vmwgfx: Use a mutex to protect gui positioning in vmw_display_unit

To avoid race condition between update_layout ioctl and modeset ioctl
for access to gui_x/y positioning added a new mutex
requested_layout_mutex.

Also used drm_for_each_connector_iter to iterate over connector list.
Signed-off-by: default avatarDeepak Rawat <drawat@vmware.com>
Reviewed-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
parent 018f60b2
...@@ -644,6 +644,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) ...@@ -644,6 +644,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
mutex_init(&dev_priv->cmdbuf_mutex); mutex_init(&dev_priv->cmdbuf_mutex);
mutex_init(&dev_priv->release_mutex); mutex_init(&dev_priv->release_mutex);
mutex_init(&dev_priv->binding_mutex); mutex_init(&dev_priv->binding_mutex);
mutex_init(&dev_priv->requested_layout_mutex);
mutex_init(&dev_priv->global_kms_state_mutex); mutex_init(&dev_priv->global_kms_state_mutex);
rwlock_init(&dev_priv->resource_lock); rwlock_init(&dev_priv->resource_lock);
ttm_lock_init(&dev_priv->reservation_sem); ttm_lock_init(&dev_priv->reservation_sem);
......
...@@ -411,6 +411,15 @@ struct vmw_private { ...@@ -411,6 +411,15 @@ struct vmw_private {
uint32_t num_displays; uint32_t num_displays;
/*
* Currently requested_layout_mutex is used to protect the gui
* positionig state in display unit. With that use case currently this
* mutex is only taken during layout ioctl and atomic check_modeset.
* Other display unit state can be protected with this mutex but that
* needs careful consideration.
*/
struct mutex requested_layout_mutex;
/* /*
* Framebuffer info. * Framebuffer info.
*/ */
......
...@@ -1577,6 +1577,7 @@ static int vmw_kms_check_display_memory(struct drm_device *dev, ...@@ -1577,6 +1577,7 @@ static int vmw_kms_check_display_memory(struct drm_device *dev,
static int vmw_kms_check_topology(struct drm_device *dev, static int vmw_kms_check_topology(struct drm_device *dev,
struct drm_atomic_state *state) struct drm_atomic_state *state)
{ {
struct vmw_private *dev_priv = vmw_priv(dev);
struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc_state *old_crtc_state, *new_crtc_state;
struct drm_rect *rects; struct drm_rect *rects;
struct drm_crtc *crtc; struct drm_crtc *crtc;
...@@ -1588,6 +1589,8 @@ static int vmw_kms_check_topology(struct drm_device *dev, ...@@ -1588,6 +1589,8 @@ static int vmw_kms_check_topology(struct drm_device *dev,
if (!rects) if (!rects)
return -ENOMEM; return -ENOMEM;
mutex_lock(&dev_priv->requested_layout_mutex);
drm_for_each_crtc(crtc, dev) { drm_for_each_crtc(crtc, dev) {
struct vmw_display_unit *du = vmw_crtc_to_du(crtc); struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
struct drm_crtc_state *crtc_state = crtc->state; struct drm_crtc_state *crtc_state = crtc->state;
...@@ -1595,10 +1598,6 @@ static int vmw_kms_check_topology(struct drm_device *dev, ...@@ -1595,10 +1598,6 @@ static int vmw_kms_check_topology(struct drm_device *dev,
i = drm_crtc_index(crtc); i = drm_crtc_index(crtc);
if (crtc_state && crtc_state->enable) { if (crtc_state && crtc_state->enable) {
/*
* There could be a race condition with update of gui_x/
* gui_y. Those are protected by dev->mode_config.mutex.
*/
rects[i].x1 = du->gui_x; rects[i].x1 = du->gui_x;
rects[i].y1 = du->gui_y; rects[i].y1 = du->gui_y;
rects[i].x2 = du->gui_x + crtc_state->mode.hdisplay; rects[i].x2 = du->gui_x + crtc_state->mode.hdisplay;
...@@ -1636,6 +1635,7 @@ static int vmw_kms_check_topology(struct drm_device *dev, ...@@ -1636,6 +1635,7 @@ static int vmw_kms_check_topology(struct drm_device *dev,
rects); rects);
clean: clean:
mutex_unlock(&dev_priv->requested_layout_mutex);
kfree(rects); kfree(rects);
return ret; return ret;
} }
...@@ -1987,10 +1987,14 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv, ...@@ -1987,10 +1987,14 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv,
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
struct vmw_display_unit *du; struct vmw_display_unit *du;
struct drm_connector *con; struct drm_connector *con;
struct drm_connector_list_iter conn_iter;
mutex_lock(&dev->mode_config.mutex); /*
* Currently only gui_x/y is protected with requested_layout_mutex.
list_for_each_entry(con, &dev->mode_config.connector_list, head) { */
mutex_lock(&dev_priv->requested_layout_mutex);
drm_connector_list_iter_begin(dev, &conn_iter);
drm_for_each_connector_iter(con, &conn_iter) {
du = vmw_connector_to_du(con); du = vmw_connector_to_du(con);
if (num_rects > du->unit) { if (num_rects > du->unit) {
du->pref_width = drm_rect_width(&rects[du->unit]); du->pref_width = drm_rect_width(&rects[du->unit]);
...@@ -1998,6 +2002,21 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv, ...@@ -1998,6 +2002,21 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv,
du->pref_active = true; du->pref_active = true;
du->gui_x = rects[du->unit].x1; du->gui_x = rects[du->unit].x1;
du->gui_y = rects[du->unit].y1; du->gui_y = rects[du->unit].y1;
} else {
du->pref_width = 800;
du->pref_height = 600;
du->pref_active = false;
du->gui_x = 0;
du->gui_y = 0;
}
}
drm_connector_list_iter_end(&conn_iter);
mutex_unlock(&dev_priv->requested_layout_mutex);
mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(con, &dev->mode_config.connector_list, head) {
du = vmw_connector_to_du(con);
if (num_rects > du->unit) {
drm_object_property_set_value drm_object_property_set_value
(&con->base, dev->mode_config.suggested_x_property, (&con->base, dev->mode_config.suggested_x_property,
du->gui_x); du->gui_x);
...@@ -2005,9 +2024,6 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv, ...@@ -2005,9 +2024,6 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv,
(&con->base, dev->mode_config.suggested_y_property, (&con->base, dev->mode_config.suggested_y_property,
du->gui_y); du->gui_y);
} else { } else {
du->pref_width = 800;
du->pref_height = 600;
du->pref_active = false;
drm_object_property_set_value drm_object_property_set_value
(&con->base, dev->mode_config.suggested_x_property, (&con->base, dev->mode_config.suggested_x_property,
0); 0);
...@@ -2017,8 +2033,8 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv, ...@@ -2017,8 +2033,8 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv,
} }
con->status = vmw_du_connector_detect(con, true); con->status = vmw_du_connector_detect(con, true);
} }
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
drm_sysfs_hotplug_event(dev); drm_sysfs_hotplug_event(dev);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment