This series is to address various unrecoverable black screen issues: after mode set or during initial installation. To work around these issues, we have to be conservative about which modes to make available. This approach may potentially cause a regression for advanced users who want higher-res modes at a lower color format (bpp).
To prevent this regression, we introduced a new vmwgfx kernel parameter.
In a low-memory 2D VM, fbdev can take up a large percentage of available memory, making them unavailable for other DRM clients.
Since we do not take fbdev into account when filtering modes, we end up claiming to support more modes than we actually do.
The current mode filtering mechanism keys off of SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB, i.e. the maximum amount of surface memory we have. Since this value is a performance suggestion, not a hard limit, and since there should not be much of a performance impact for a 2D VM, rather than filtering out more modes, we will just allow ourselves to exceed the SVGA's performance suggestion.
Also changed assumed bpp to 32 from 16 to make sure we can actually support all the modes listed.
Signed-off-by: Sinclair Yeh syeh@vmware.com Reviewed-by: Thomas Hellstrom thellstrom@vmware.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 +++++++ drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 9 +-------- 2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 9fcd820..fc9ad00 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -706,6 +706,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, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 55231cc..077f16d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1553,14 +1553,7 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }; int i; - u32 assumed_bpp = 2; - - /* - * 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; + u32 assumed_bpp = 4;
if (dev_priv->active_display_unit == vmw_du_screen_target) { max_width = min(max_width, dev_priv->stdu_max_width);
Offer an option for advanced users who want larger modes at 16bpp.
This becomes necessary after the fix: "Work around mode set failure in 2D VMs." Without this patch, there would be no way for existing advanced users to get to a high res mode.
Signed-off-by: Sinclair Yeh syeh@vmware.com Reviewed-by: Thomas Hellstrom thellstrom@vmware.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 5 +++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 3 +++ 3 files changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index fc9ad00..8d528fc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -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); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 1980e2a..89fb194 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -386,6 +386,7 @@ struct vmw_private { spinlock_t hw_lock; spinlock_t cap_lock; bool has_dx; + bool assume_16bpp;
/* * VGA registers. diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 077f16d..e29da45 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1555,6 +1555,9 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, int i; u32 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); max_height = min(max_height, dev_priv->stdu_max_height);
dri-devel@lists.freedesktop.org