Merge branch 'drm-vmwgfx-fixes' of git://people.freedesktop.org/~syeh/repos_linux into drm-fixes
A bunch of vmwgfx fixes that fix a black screen issue on latest distros/hw combos. * 'drm-vmwgfx-fixes' of git://people.freedesktop.org/~syeh/repos_linux: drm/vmwgfx: Fix error paths when mapping framebuffer drm/vmwgfx: Fix corner case screen target management drm/vmwgfx: Delay pinning fbdev framebuffer until after mode set drm/vmwgfx: Check pin count before attempting to move a buffer drm/ttm: Make ttm_bo_mem_compat available drm/vmwgfx: Add an option to change assumed FB bpp drm/vmwgfx: Work around mode set failure in 2D VMs drm/vmwgfx: Add a check to handle host message failure
This commit is contained in:
commit
d2e1204f89
@ -1034,9 +1034,9 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool ttm_bo_mem_compat(struct ttm_placement *placement,
|
||||
struct ttm_mem_reg *mem,
|
||||
uint32_t *new_flags)
|
||||
bool ttm_bo_mem_compat(struct ttm_placement *placement,
|
||||
struct ttm_mem_reg *mem,
|
||||
uint32_t *new_flags)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1068,6 +1068,7 @@ static bool ttm_bo_mem_compat(struct ttm_placement *placement,
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_bo_mem_compat);
|
||||
|
||||
int ttm_bo_validate(struct ttm_buffer_object *bo,
|
||||
struct ttm_placement *placement,
|
||||
|
@ -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);
|
||||
|
@ -233,6 +233,7 @@ static int vmw_force_iommu;
|
||||
static int vmw_restrict_iommu;
|
||||
static int vmw_force_coherent;
|
||||
static int vmw_restrict_dma_mask;
|
||||
static int vmw_assume_16bpp;
|
||||
|
||||
static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
|
||||
static void vmw_master_init(struct vmw_master *);
|
||||
@ -249,6 +250,8 @@ MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
|
||||
module_param_named(force_coherent, vmw_force_coherent, int, 0600);
|
||||
MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU");
|
||||
module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, 0600);
|
||||
MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes");
|
||||
module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600);
|
||||
|
||||
|
||||
static void vmw_print_capabilities(uint32_t capabilities)
|
||||
@ -660,6 +663,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
|
||||
dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
|
||||
|
||||
dev_priv->assume_16bpp = !!vmw_assume_16bpp;
|
||||
|
||||
dev_priv->enable_fb = enable_fbdev;
|
||||
|
||||
vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
|
||||
@ -706,6 +711,13 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
vmw_read(dev_priv,
|
||||
SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB);
|
||||
|
||||
/*
|
||||
* Workaround for low memory 2D VMs to compensate for the
|
||||
* allocation taken by fbdev
|
||||
*/
|
||||
if (!(dev_priv->capabilities & SVGA_CAP_3D))
|
||||
mem_size *= 2;
|
||||
|
||||
dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE;
|
||||
dev_priv->prim_bb_mem =
|
||||
vmw_read(dev_priv,
|
||||
|
@ -386,6 +386,7 @@ struct vmw_private {
|
||||
spinlock_t hw_lock;
|
||||
spinlock_t cap_lock;
|
||||
bool has_dx;
|
||||
bool assume_16bpp;
|
||||
|
||||
/*
|
||||
* VGA registers.
|
||||
|
@ -517,28 +517,6 @@ static int vmw_fb_kms_framebuffer(struct fb_info *info)
|
||||
|
||||
par->set_fb = &vfb->base;
|
||||
|
||||
if (!par->bo_ptr) {
|
||||
/*
|
||||
* Pin before mapping. Since we don't know in what placement
|
||||
* to pin, call into KMS to do it for us.
|
||||
*/
|
||||
ret = vfb->pin(vfb);
|
||||
if (ret) {
|
||||
DRM_ERROR("Could not pin the fbdev framebuffer.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ttm_bo_kmap(&par->vmw_bo->base, 0,
|
||||
par->vmw_bo->base.num_pages, &par->map);
|
||||
if (ret) {
|
||||
vfb->unpin(vfb);
|
||||
DRM_ERROR("Could not map the fbdev framebuffer.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -601,6 +579,31 @@ static int vmw_fb_set_par(struct fb_info *info)
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
if (!par->bo_ptr) {
|
||||
struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(set.fb);
|
||||
|
||||
/*
|
||||
* Pin before mapping. Since we don't know in what placement
|
||||
* to pin, call into KMS to do it for us.
|
||||
*/
|
||||
ret = vfb->pin(vfb);
|
||||
if (ret) {
|
||||
DRM_ERROR("Could not pin the fbdev framebuffer.\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = ttm_bo_kmap(&par->vmw_bo->base, 0,
|
||||
par->vmw_bo->base.num_pages, &par->map);
|
||||
if (ret) {
|
||||
vfb->unpin(vfb);
|
||||
DRM_ERROR("Could not map the fbdev framebuffer.\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
|
||||
}
|
||||
|
||||
|
||||
vmw_fb_dirty_mark(par, par->fb_x, par->fb_y,
|
||||
par->set_fb->width, par->set_fb->height);
|
||||
|
||||
|
@ -1553,14 +1553,10 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
|
||||
};
|
||||
int i;
|
||||
u32 assumed_bpp = 2;
|
||||
u32 assumed_bpp = 4;
|
||||
|
||||
/*
|
||||
* If using screen objects, then assume 32-bpp because that's what the
|
||||
* SVGA device is assuming
|
||||
*/
|
||||
if (dev_priv->active_display_unit == vmw_du_screen_object)
|
||||
assumed_bpp = 4;
|
||||
if (dev_priv->assume_16bpp)
|
||||
assumed_bpp = 2;
|
||||
|
||||
if (dev_priv->active_display_unit == vmw_du_screen_target) {
|
||||
max_width = min(max_width, dev_priv->stdu_max_width);
|
||||
|
@ -300,6 +300,9 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
|
||||
break;
|
||||
}
|
||||
|
||||
if (retries == RETRIES)
|
||||
return -EINVAL;
|
||||
|
||||
*msg_len = reply_len;
|
||||
*msg = reply;
|
||||
|
||||
|
@ -399,8 +399,10 @@ static int vmw_stdu_bind_fb(struct vmw_private *dev_priv,
|
||||
|
||||
WARN_ON_ONCE(!stdu->defined);
|
||||
|
||||
if (!vfb->dmabuf && new_fb->width == mode->hdisplay &&
|
||||
new_fb->height == mode->vdisplay)
|
||||
new_vfbs = (vfb->dmabuf) ? NULL : vmw_framebuffer_to_vfbs(new_fb);
|
||||
|
||||
if (new_vfbs && new_vfbs->surface->base_size.width == mode->hdisplay &&
|
||||
new_vfbs->surface->base_size.height == mode->vdisplay)
|
||||
new_content_type = SAME_AS_DISPLAY;
|
||||
else if (vfb->dmabuf)
|
||||
new_content_type = SEPARATE_DMA;
|
||||
@ -444,7 +446,6 @@ static int vmw_stdu_bind_fb(struct vmw_private *dev_priv,
|
||||
content_srf.mip_levels[0] = 1;
|
||||
content_srf.multisample_count = 0;
|
||||
} else {
|
||||
new_vfbs = vmw_framebuffer_to_vfbs(new_fb);
|
||||
content_srf = *new_vfbs->surface;
|
||||
}
|
||||
|
||||
@ -464,7 +465,6 @@ static int vmw_stdu_bind_fb(struct vmw_private *dev_priv,
|
||||
return ret;
|
||||
}
|
||||
} else if (new_content_type == SAME_AS_DISPLAY) {
|
||||
new_vfbs = vmw_framebuffer_to_vfbs(new_fb);
|
||||
new_display_srf = vmw_surface_reference(new_vfbs->surface);
|
||||
}
|
||||
|
||||
|
@ -316,6 +316,20 @@ ttm_bo_reference(struct ttm_buffer_object *bo)
|
||||
*/
|
||||
extern int ttm_bo_wait(struct ttm_buffer_object *bo,
|
||||
bool interruptible, bool no_wait);
|
||||
|
||||
/**
|
||||
* ttm_bo_mem_compat - Check if proposed placement is compatible with a bo
|
||||
*
|
||||
* @placement: Return immediately if buffer is busy.
|
||||
* @mem: The struct ttm_mem_reg indicating the region where the bo resides
|
||||
* @new_flags: Describes compatible placement found
|
||||
*
|
||||
* Returns true if the placement is compatible
|
||||
*/
|
||||
extern bool ttm_bo_mem_compat(struct ttm_placement *placement,
|
||||
struct ttm_mem_reg *mem,
|
||||
uint32_t *new_flags);
|
||||
|
||||
/**
|
||||
* ttm_bo_validate
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user