diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2010-10-05 06:43:04 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-10-05 21:29:51 -0400 |
commit | e133e7371231e49c3e7d626e2251cb6f7c3ca1ad (patch) | |
tree | fbe8453b1243993e96f961f69b328cda05d096ab /drivers/gpu/drm | |
parent | 3a939a5ece3030e60c966a885c8e9bd329c4faf7 (diff) |
drm/vmwgfx: Prune modes based on available VRAM size
This needs to be reviewed once we support screen objects and don't rely
on VRAM for the frame-buffer.
Also fix some integer overflow issues pointed out by Michel Daenzer.
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 28 |
4 files changed, 38 insertions, 11 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 0ab53d98310..a10d0ad3103 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
@@ -522,6 +522,9 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv, | |||
522 | int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, | 522 | int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, |
523 | struct drm_file *file_priv); | 523 | struct drm_file *file_priv); |
524 | void vmw_kms_idle_workqueues(struct vmw_master *vmaster); | 524 | void vmw_kms_idle_workqueues(struct vmw_master *vmaster); |
525 | bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv, | ||
526 | uint32_t pitch, | ||
527 | uint32_t height); | ||
525 | u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc); | 528 | u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc); |
526 | 529 | ||
527 | /** | 530 | /** |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 409e172f4ab..086ef049026 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | |||
@@ -144,6 +144,13 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var, | |||
144 | return -EINVAL; | 144 | return -EINVAL; |
145 | } | 145 | } |
146 | 146 | ||
147 | if (!vmw_kms_validate_mode_vram(vmw_priv, | ||
148 | info->fix.line_length, | ||
149 | var->yoffset + var->yres)) { | ||
150 | DRM_ERROR("Requested geom can not fit in framebuffer\n"); | ||
151 | return -EINVAL; | ||
152 | } | ||
153 | |||
147 | return 0; | 154 | return 0; |
148 | } | 155 | } |
149 | 156 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 82bd3d8c0e4..5fb68f3981a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -838,7 +838,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, | |||
838 | struct vmw_framebuffer *vfb = NULL; | 838 | struct vmw_framebuffer *vfb = NULL; |
839 | struct vmw_surface *surface = NULL; | 839 | struct vmw_surface *surface = NULL; |
840 | struct vmw_dma_buffer *bo = NULL; | 840 | struct vmw_dma_buffer *bo = NULL; |
841 | unsigned int required_size; | 841 | u64 required_size; |
842 | int ret; | 842 | int ret; |
843 | 843 | ||
844 | /** | 844 | /** |
@@ -848,7 +848,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, | |||
848 | */ | 848 | */ |
849 | 849 | ||
850 | required_size = mode_cmd->pitch * mode_cmd->height; | 850 | required_size = mode_cmd->pitch * mode_cmd->height; |
851 | if (unlikely(required_size > dev_priv->vram_size)) { | 851 | if (unlikely(required_size > (u64) dev_priv->vram_size)) { |
852 | DRM_ERROR("VRAM size is too small for requested mode.\n"); | 852 | DRM_ERROR("VRAM size is too small for requested mode.\n"); |
853 | return NULL; | 853 | return NULL; |
854 | } | 854 | } |
@@ -1133,6 +1133,13 @@ out_unlock: | |||
1133 | return ret; | 1133 | return ret; |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv, | ||
1137 | uint32_t pitch, | ||
1138 | uint32_t height) | ||
1139 | { | ||
1140 | return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size; | ||
1141 | } | ||
1142 | |||
1136 | u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc) | 1143 | u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc) |
1137 | { | 1144 | { |
1138 | return 0; | 1145 | return 0; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 11cb39e3acc..a01c47ddb5b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |||
@@ -427,7 +427,9 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, | |||
427 | { | 427 | { |
428 | struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector); | 428 | struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector); |
429 | struct drm_device *dev = connector->dev; | 429 | struct drm_device *dev = connector->dev; |
430 | struct vmw_private *dev_priv = vmw_priv(dev); | ||
430 | struct drm_display_mode *mode = NULL; | 431 | struct drm_display_mode *mode = NULL; |
432 | struct drm_display_mode *bmode; | ||
431 | struct drm_display_mode prefmode = { DRM_MODE("preferred", | 433 | struct drm_display_mode prefmode = { DRM_MODE("preferred", |
432 | DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, | 434 | DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, |
433 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 435 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
@@ -443,22 +445,30 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, | |||
443 | mode->hdisplay = ldu->pref_width; | 445 | mode->hdisplay = ldu->pref_width; |
444 | mode->vdisplay = ldu->pref_height; | 446 | mode->vdisplay = ldu->pref_height; |
445 | mode->vrefresh = drm_mode_vrefresh(mode); | 447 | mode->vrefresh = drm_mode_vrefresh(mode); |
446 | drm_mode_probed_add(connector, mode); | 448 | if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2, |
449 | mode->vdisplay)) { | ||
450 | drm_mode_probed_add(connector, mode); | ||
447 | 451 | ||
448 | if (ldu->pref_mode) { | 452 | if (ldu->pref_mode) { |
449 | list_del_init(&ldu->pref_mode->head); | 453 | list_del_init(&ldu->pref_mode->head); |
450 | drm_mode_destroy(dev, ldu->pref_mode); | 454 | drm_mode_destroy(dev, ldu->pref_mode); |
451 | } | 455 | } |
452 | 456 | ||
453 | ldu->pref_mode = mode; | 457 | ldu->pref_mode = mode; |
458 | } | ||
454 | } | 459 | } |
455 | 460 | ||
456 | for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) { | 461 | for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) { |
457 | if (vmw_ldu_connector_builtin[i].hdisplay > max_width || | 462 | bmode = &vmw_ldu_connector_builtin[i]; |
458 | vmw_ldu_connector_builtin[i].vdisplay > max_height) | 463 | if (bmode->hdisplay > max_width || |
464 | bmode->vdisplay > max_height) | ||
465 | continue; | ||
466 | |||
467 | if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2, | ||
468 | bmode->vdisplay)) | ||
459 | continue; | 469 | continue; |
460 | 470 | ||
461 | mode = drm_mode_duplicate(dev, &vmw_ldu_connector_builtin[i]); | 471 | mode = drm_mode_duplicate(dev, bmode); |
462 | if (!mode) | 472 | if (!mode) |
463 | return 0; | 473 | return 0; |
464 | mode->vrefresh = drm_mode_vrefresh(mode); | 474 | mode->vrefresh = drm_mode_vrefresh(mode); |