aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2010-10-05 06:43:04 -0400
committerDave Airlie <airlied@redhat.com>2010-10-05 21:29:51 -0400
commite133e7371231e49c3e7d626e2251cb6f7c3ca1ad (patch)
treefbe8453b1243993e96f961f69b328cda05d096ab /drivers/gpu/drm
parent3a939a5ece3030e60c966a885c8e9bd329c4faf7 (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.h3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c11
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c28
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,
522int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, 522int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
523 struct drm_file *file_priv); 523 struct drm_file *file_priv);
524void vmw_kms_idle_workqueues(struct vmw_master *vmaster); 524void vmw_kms_idle_workqueues(struct vmw_master *vmaster);
525bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
526 uint32_t pitch,
527 uint32_t height);
525u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc); 528u32 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
1136bool 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
1136u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc) 1143u32 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);