Add the mode_valid() callback in drm_mode_config_funcs to check for valid mode during drm_mode_setcrtc. Both the mode_valid() callbacks also check if the vrefresh value is correct. This fixes igt test kms_invalid_mode@overflow-vrefresh.
Signed-off-by: Maaz Mombasawala <[email protected]> --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 28 ++++++++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 9 +++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 12 +++--------- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 55730e29d3ae..121a4f006804 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1062,8 +1062,36 @@ vmw_kms_atomic_check_modeset(struct drm_device *dev, return ret; } +static enum drm_mode_status +vmw_kms_config_mode_valid(struct drm_device *dev, + const struct drm_display_mode *mode) +{ + enum drm_mode_status ret; + struct vmw_private *dev_priv = vmw_priv(dev); + u64 assumed_cpp = dev_priv->assume_16bpp ? 2 : 4; + /* Align width and height to account for GPU tile over-alignment */ + u64 required_mem = ALIGN(mode->hdisplay, GPU_TILE_SIZE) * + ALIGN(mode->vdisplay, GPU_TILE_SIZE) * + assumed_cpp; + required_mem = ALIGN(required_mem, PAGE_SIZE); + + ret = drm_mode_validate_size(mode, dev_priv->texture_max_width, + dev_priv->texture_max_height); + if (ret != MODE_OK) + return ret; + + if (required_mem > dev_priv->max_primary_mem) + return MODE_MEM; + + if (!drm_mode_vrefresh(mode)) + return MODE_BAD; + + return MODE_OK; +} + static const struct drm_mode_config_funcs vmw_kms_funcs = { .fb_create = vmw_kms_fb_create, + .mode_valid = vmw_kms_config_mode_valid, .atomic_check = vmw_kms_atomic_check_modeset, .atomic_commit = drm_atomic_helper_commit, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 445471fe9be6..ea12f6c77f2d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -16,6 +16,15 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_probe_helper.h> +/* + * Some renderers such as llvmpipe will align the width and height of their + * buffers to match their tile size. We need to keep this in mind when exposing + * modes to userspace so that this possible over-allocation will not exceed + * graphics memory. 64x64 pixels seems to be a reasonable upper bound for the + * tile size of current renderers. + */ +#define GPU_TILE_SIZE 64 + /** * struct vmw_du_update_plane - Closure structure for vmw_du_helper_plane_update * @plane: Plane which is being updated. diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index dcbacee97f61..17dc20b2ec64 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -45,15 +45,6 @@ #define vmw_connector_to_stdu(x) \ container_of(x, struct vmw_screen_target_display_unit, base.connector) -/* - * Some renderers such as llvmpipe will align the width and height of their - * buffers to match their tile size. We need to keep this in mind when exposing - * modes to userspace so that this possible over-allocation will not exceed - * graphics memory. 64x64 pixels seems to be a reasonable upper bound for the - * tile size of current renderers. - */ -#define GPU_TILE_SIZE 64 - enum stdu_content_type { SAME_AS_DISPLAY = 0, SEPARATE_SURFACE, @@ -870,6 +861,9 @@ vmw_stdu_connector_mode_valid(struct drm_connector *connector, if (required_mem > dev_priv->max_mob_size) return MODE_MEM; + if (!drm_mode_vrefresh(mode)) + return MODE_BAD; + return MODE_OK; } -- 2.54.0
