diff options
author | Deepak Rawat <drawat@vmware.com> | 2018-06-20 05:32:29 -0400 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2018-07-03 14:39:30 -0400 |
commit | b89e5ff9eeeb8b1fe3d2d7477fb9e1c1aed5dd5b (patch) | |
tree | 0ae81b27b297a1482b00587baceeebd451fa33f7 | |
parent | 018f60b26602bb41b33139da3408224e36dfe02d (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.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 38 |
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, | |||
1577 | static int vmw_kms_check_topology(struct drm_device *dev, | 1577 | static 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 | ||
1638 | clean: | 1637 | clean: |
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; |