aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Rawat <drawat@vmware.com>2018-06-20 05:32:29 -0400
committerThomas Hellstrom <thellstrom@vmware.com>2018-07-03 14:39:30 -0400
commitb89e5ff9eeeb8b1fe3d2d7477fb9e1c1aed5dd5b (patch)
tree0ae81b27b297a1482b00587baceeebd451fa33f7
parent018f60b26602bb41b33139da3408224e36dfe02d (diff)
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: Deepak Rawat <drawat@vmware.com> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h9
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c38
3 files changed, 37 insertions, 11 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 4f18304226bc..45dfff7733d6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -644,6 +644,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
644 mutex_init(&dev_priv->cmdbuf_mutex); 644 mutex_init(&dev_priv->cmdbuf_mutex);
645 mutex_init(&dev_priv->release_mutex); 645 mutex_init(&dev_priv->release_mutex);
646 mutex_init(&dev_priv->binding_mutex); 646 mutex_init(&dev_priv->binding_mutex);
647 mutex_init(&dev_priv->requested_layout_mutex);
647 mutex_init(&dev_priv->global_kms_state_mutex); 648 mutex_init(&dev_priv->global_kms_state_mutex);
648 rwlock_init(&dev_priv->resource_lock); 649 rwlock_init(&dev_priv->resource_lock);
649 ttm_lock_init(&dev_priv->reservation_sem); 650 ttm_lock_init(&dev_priv->reservation_sem);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 769d72fabb56..a38318c3efe4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -412,6 +412,15 @@ struct vmw_private {
412 uint32_t num_displays; 412 uint32_t num_displays;
413 413
414 /* 414 /*
415 * Currently requested_layout_mutex is used to protect the gui
416 * positionig state in display unit. With that use case currently this
417 * mutex is only taken during layout ioctl and atomic check_modeset.
418 * Other display unit state can be protected with this mutex but that
419 * needs careful consideration.
420 */
421 struct mutex requested_layout_mutex;
422
423 /*
415 * Framebuffer info. 424 * Framebuffer info.
416 */ 425 */
417 426
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index f0ae0b2ee2e6..a592d10e5c76 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1577,6 +1577,7 @@ static int vmw_kms_check_display_memory(struct drm_device *dev,
1577static int vmw_kms_check_topology(struct drm_device *dev, 1577static int vmw_kms_check_topology(struct drm_device *dev,
1578 struct drm_atomic_state *state) 1578 struct drm_atomic_state *state)
1579{ 1579{
1580 struct vmw_private *dev_priv = vmw_priv(dev);
1580 struct drm_crtc_state *old_crtc_state, *new_crtc_state; 1581 struct drm_crtc_state *old_crtc_state, *new_crtc_state;
1581 struct drm_rect *rects; 1582 struct drm_rect *rects;
1582 struct drm_crtc *crtc; 1583 struct drm_crtc *crtc;
@@ -1588,6 +1589,8 @@ static int vmw_kms_check_topology(struct drm_device *dev,
1588 if (!rects) 1589 if (!rects)
1589 return -ENOMEM; 1590 return -ENOMEM;
1590 1591
1592 mutex_lock(&dev_priv->requested_layout_mutex);
1593
1591 drm_for_each_crtc(crtc, dev) { 1594 drm_for_each_crtc(crtc, dev) {
1592 struct vmw_display_unit *du = vmw_crtc_to_du(crtc); 1595 struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
1593 struct drm_crtc_state *crtc_state = crtc->state; 1596 struct drm_crtc_state *crtc_state = crtc->state;
@@ -1595,10 +1598,6 @@ static int vmw_kms_check_topology(struct drm_device *dev,
1595 i = drm_crtc_index(crtc); 1598 i = drm_crtc_index(crtc);
1596 1599
1597 if (crtc_state && crtc_state->enable) { 1600 if (crtc_state && crtc_state->enable) {
1598 /*
1599 * There could be a race condition with update of gui_x/
1600 * gui_y. Those are protected by dev->mode_config.mutex.
1601 */
1602 rects[i].x1 = du->gui_x; 1601 rects[i].x1 = du->gui_x;
1603 rects[i].y1 = du->gui_y; 1602 rects[i].y1 = du->gui_y;
1604 rects[i].x2 = du->gui_x + crtc_state->mode.hdisplay; 1603 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 rects); 1635 rects);
1637 1636
1638clean: 1637clean:
1638 mutex_unlock(&dev_priv->requested_layout_mutex);
1639 kfree(rects); 1639 kfree(rects);
1640 return ret; 1640 return ret;
1641} 1641}
@@ -1987,10 +1987,14 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv,
1987 struct drm_device *dev = dev_priv->dev; 1987 struct drm_device *dev = dev_priv->dev;
1988 struct vmw_display_unit *du; 1988 struct vmw_display_unit *du;
1989 struct drm_connector *con; 1989 struct drm_connector *con;
1990 struct drm_connector_list_iter conn_iter;
1990 1991
1991 mutex_lock(&dev->mode_config.mutex); 1992 /*
1992 1993 * Currently only gui_x/y is protected with requested_layout_mutex.
1993 list_for_each_entry(con, &dev->mode_config.connector_list, head) { 1994 */
1995 mutex_lock(&dev_priv->requested_layout_mutex);
1996 drm_connector_list_iter_begin(dev, &conn_iter);
1997 drm_for_each_connector_iter(con, &conn_iter) {
1994 du = vmw_connector_to_du(con); 1998 du = vmw_connector_to_du(con);
1995 if (num_rects > du->unit) { 1999 if (num_rects > du->unit) {
1996 du->pref_width = drm_rect_width(&rects[du->unit]); 2000 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 du->pref_active = true; 2002 du->pref_active = true;
1999 du->gui_x = rects[du->unit].x1; 2003 du->gui_x = rects[du->unit].x1;
2000 du->gui_y = rects[du->unit].y1; 2004 du->gui_y = rects[du->unit].y1;
2005 } else {
2006 du->pref_width = 800;
2007 du->pref_height = 600;
2008 du->pref_active = false;
2009 du->gui_x = 0;
2010 du->gui_y = 0;
2011 }
2012 }
2013 drm_connector_list_iter_end(&conn_iter);
2014 mutex_unlock(&dev_priv->requested_layout_mutex);
2015
2016 mutex_lock(&dev->mode_config.mutex);
2017 list_for_each_entry(con, &dev->mode_config.connector_list, head) {
2018 du = vmw_connector_to_du(con);
2019 if (num_rects > du->unit) {
2001 drm_object_property_set_value 2020 drm_object_property_set_value
2002 (&con->base, dev->mode_config.suggested_x_property, 2021 (&con->base, dev->mode_config.suggested_x_property,
2003 du->gui_x); 2022 du->gui_x);
@@ -2005,9 +2024,6 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv,
2005 (&con->base, dev->mode_config.suggested_y_property, 2024 (&con->base, dev->mode_config.suggested_y_property,
2006 du->gui_y); 2025 du->gui_y);
2007 } else { 2026 } else {
2008 du->pref_width = 800;
2009 du->pref_height = 600;
2010 du->pref_active = false;
2011 drm_object_property_set_value 2027 drm_object_property_set_value
2012 (&con->base, dev->mode_config.suggested_x_property, 2028 (&con->base, dev->mode_config.suggested_x_property,
2013 0); 2029 0);
@@ -2017,8 +2033,8 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv,
2017 } 2033 }
2018 con->status = vmw_du_connector_detect(con, true); 2034 con->status = vmw_du_connector_detect(con, true);
2019 } 2035 }
2020
2021 mutex_unlock(&dev->mode_config.mutex); 2036 mutex_unlock(&dev->mode_config.mutex);
2037
2022 drm_sysfs_hotplug_event(dev); 2038 drm_sysfs_hotplug_event(dev);
2023 2039
2024 return 0; 2040 return 0;