mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-08 02:21:18 +00:00
drm/vmwgfx: Check pin count before attempting to move a buffer
In certain scenarios, e.g. when fbdev is enabled, we can get into a situation where a vmw_framebuffer_pin() is called on a buffer that is already pinned. When this happens, ttm_bo_validate() will unintentially remove the TTM_PL_FLAG_NO_EVICT flag, thus unpinning it, and leaving no way to actually pin the buffer again. To prevent this, if a buffer is already pinned, then instead of calling ttm_bo_validate(), just make sure the proposed placement is compatible with the existing placement. Signed-off-by: Sinclair Yeh <syeh@vmware.com> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com> Cc: <stable@vger.kernel.org> --- This is the 2nd patch in a 3-patch series to fix a console black screen issue on Ubuntu 16.04 server. This fixes a BUG_ON() condition where a pinned buffer gets accidentally put onto the LRU list.
This commit is contained in:
parent
94477bff39
commit
4ed7e2242b
@ -49,6 +49,7 @@ int vmw_dmabuf_pin_in_placement(struct vmw_private *dev_priv,
|
|||||||
{
|
{
|
||||||
struct ttm_buffer_object *bo = &buf->base;
|
struct ttm_buffer_object *bo = &buf->base;
|
||||||
int ret;
|
int ret;
|
||||||
|
uint32_t new_flags;
|
||||||
|
|
||||||
ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
|
ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
|
||||||
if (unlikely(ret != 0))
|
if (unlikely(ret != 0))
|
||||||
@ -60,7 +61,12 @@ int vmw_dmabuf_pin_in_placement(struct vmw_private *dev_priv,
|
|||||||
if (unlikely(ret != 0))
|
if (unlikely(ret != 0))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ret = ttm_bo_validate(bo, placement, interruptible, false);
|
if (buf->pin_count > 0)
|
||||||
|
ret = ttm_bo_mem_compat(placement, &bo->mem,
|
||||||
|
&new_flags) == true ? 0 : -EINVAL;
|
||||||
|
else
|
||||||
|
ret = ttm_bo_validate(bo, placement, interruptible, false);
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
vmw_bo_pin_reserved(buf, true);
|
vmw_bo_pin_reserved(buf, true);
|
||||||
|
|
||||||
@ -91,6 +97,7 @@ int vmw_dmabuf_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
|
|||||||
{
|
{
|
||||||
struct ttm_buffer_object *bo = &buf->base;
|
struct ttm_buffer_object *bo = &buf->base;
|
||||||
int ret;
|
int ret;
|
||||||
|
uint32_t new_flags;
|
||||||
|
|
||||||
ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
|
ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
|
||||||
if (unlikely(ret != 0))
|
if (unlikely(ret != 0))
|
||||||
@ -102,6 +109,12 @@ int vmw_dmabuf_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
|
|||||||
if (unlikely(ret != 0))
|
if (unlikely(ret != 0))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
if (buf->pin_count > 0) {
|
||||||
|
ret = ttm_bo_mem_compat(&vmw_vram_gmr_placement, &bo->mem,
|
||||||
|
&new_flags) == true ? 0 : -EINVAL;
|
||||||
|
goto out_unreserve;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, interruptible,
|
ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, interruptible,
|
||||||
false);
|
false);
|
||||||
if (likely(ret == 0) || ret == -ERESTARTSYS)
|
if (likely(ret == 0) || ret == -ERESTARTSYS)
|
||||||
@ -161,6 +174,7 @@ int vmw_dmabuf_pin_in_start_of_vram(struct vmw_private *dev_priv,
|
|||||||
struct ttm_placement placement;
|
struct ttm_placement placement;
|
||||||
struct ttm_place place;
|
struct ttm_place place;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
uint32_t new_flags;
|
||||||
|
|
||||||
place = vmw_vram_placement.placement[0];
|
place = vmw_vram_placement.placement[0];
|
||||||
place.lpfn = bo->num_pages;
|
place.lpfn = bo->num_pages;
|
||||||
@ -185,10 +199,15 @@ int vmw_dmabuf_pin_in_start_of_vram(struct vmw_private *dev_priv,
|
|||||||
*/
|
*/
|
||||||
if (bo->mem.mem_type == TTM_PL_VRAM &&
|
if (bo->mem.mem_type == TTM_PL_VRAM &&
|
||||||
bo->mem.start < bo->num_pages &&
|
bo->mem.start < bo->num_pages &&
|
||||||
bo->mem.start > 0)
|
bo->mem.start > 0 &&
|
||||||
|
buf->pin_count == 0)
|
||||||
(void) ttm_bo_validate(bo, &vmw_sys_placement, false, false);
|
(void) ttm_bo_validate(bo, &vmw_sys_placement, false, false);
|
||||||
|
|
||||||
ret = ttm_bo_validate(bo, &placement, interruptible, false);
|
if (buf->pin_count > 0)
|
||||||
|
ret = ttm_bo_mem_compat(&placement, &bo->mem,
|
||||||
|
&new_flags) == true ? 0 : -EINVAL;
|
||||||
|
else
|
||||||
|
ret = ttm_bo_validate(bo, &placement, interruptible, false);
|
||||||
|
|
||||||
/* For some reason we didn't end up at the start of vram */
|
/* For some reason we didn't end up at the start of vram */
|
||||||
WARN_ON(ret == 0 && bo->offset != 0);
|
WARN_ON(ret == 0 && bo->offset != 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user