mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 14:04:54 +02:00
drm/vmwgfx: Check pin count before attempting to move a buffer
commit 4ed7e2242b upstream.
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
b40c9ac728
commit
e587d4e630
|
|
@ -49,6 +49,7 @@ int vmw_dmabuf_pin_in_placement(struct vmw_private *dev_priv,
|
|||
{
|
||||
struct ttm_buffer_object *bo = &buf->base;
|
||||
int ret;
|
||||
uint32_t new_flags;
|
||||
|
||||
ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
|
||||
if (unlikely(ret != 0))
|
||||
|
|
@ -60,7 +61,12 @@ int vmw_dmabuf_pin_in_placement(struct vmw_private *dev_priv,
|
|||
if (unlikely(ret != 0))
|
||||
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)
|
||||
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;
|
||||
int ret;
|
||||
uint32_t new_flags;
|
||||
|
||||
ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
|
||||
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))
|
||||
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,
|
||||
false);
|
||||
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_place place;
|
||||
int ret = 0;
|
||||
uint32_t new_flags;
|
||||
|
||||
place = vmw_vram_placement.placement[0];
|
||||
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 &&
|
||||
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);
|
||||
|
||||
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 */
|
||||
WARN_ON(ret == 0 && bo->offset != 0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user