drm: Reject page_flip for !DRIVER_MODESET
[pandora-kernel.git] / drivers / gpu / drm / drm_crtc.c
index 711d965..4ca454b 100644 (file)
@@ -163,6 +163,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
        { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
        { DRM_MODE_CONNECTOR_TV, "TV", 0 },
        { DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
+       { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
 };
 
 static struct drm_prop_enum_list drm_encoder_enum_list[] =
@@ -171,6 +172,7 @@ static struct drm_prop_enum_list drm_encoder_enum_list[] =
        { DRM_MODE_ENCODER_TMDS, "TMDS" },
        { DRM_MODE_ENCODER_LVDS, "LVDS" },
        { DRM_MODE_ENCODER_TVDAC, "TV" },
+       { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
 };
 
 char *drm_get_encoder_name(struct drm_encoder *encoder)
@@ -464,8 +466,10 @@ void drm_connector_init(struct drm_device *dev,
        list_add_tail(&connector->head, &dev->mode_config.connector_list);
        dev->mode_config.num_connector++;
 
-       drm_connector_attach_property(connector,
-                                     dev->mode_config.edid_property, 0);
+       if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
+               drm_connector_attach_property(connector,
+                                             dev->mode_config.edid_property,
+                                             0);
 
        drm_connector_attach_property(connector,
                                      dev->mode_config.dpms_property, 0);
@@ -1501,6 +1505,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
+       /*
+        * Universal plane src offsets are only 16.16, prevent havoc for
+        * drivers using universal plane code internally.
+        */
+       if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
+               return -ERANGE;
+
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, crtc_req->crtc_id,
                                   DRM_MODE_OBJECT_CRTC);
@@ -1621,10 +1632,8 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
-       if (!req->flags) {
-               DRM_ERROR("no operation set\n");
+       if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
                return -EINVAL;
-       }
 
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
@@ -1637,7 +1646,6 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
 
        if (req->flags & DRM_MODE_CURSOR_BO) {
                if (!crtc->funcs->cursor_set) {
-                       DRM_ERROR("crtc does not support cursor\n");
                        ret = -ENXIO;
                        goto out;
                }
@@ -1650,7 +1658,6 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
                if (crtc->funcs->cursor_move) {
                        ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
                } else {
-                       DRM_ERROR("crtc does not support cursor\n");
                        ret = -EFAULT;
                        goto out;
                }
@@ -1688,14 +1695,11 @@ int drm_mode_addfb(struct drm_device *dev,
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
-       if ((config->min_width > r->width) || (r->width > config->max_width)) {
-               DRM_ERROR("mode new framebuffer width not within limits\n");
+       if ((config->min_width > r->width) || (r->width > config->max_width))
                return -EINVAL;
-       }
-       if ((config->min_height > r->height) || (r->height > config->max_height)) {
-               DRM_ERROR("mode new framebuffer height not within limits\n");
+
+       if ((config->min_height > r->height) || (r->height > config->max_height))
                return -EINVAL;
-       }
 
        mutex_lock(&dev->mode_config.mutex);
 
@@ -1752,7 +1756,6 @@ int drm_mode_rmfb(struct drm_device *dev,
        obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
        /* TODO check that we really get a framebuffer back. */
        if (!obj) {
-               DRM_ERROR("mode invalid framebuffer id\n");
                ret = -EINVAL;
                goto out;
        }
@@ -1763,7 +1766,6 @@ int drm_mode_rmfb(struct drm_device *dev,
                        found = 1;
 
        if (!found) {
-               DRM_ERROR("tried to remove a fb that we didn't own\n");
                ret = -EINVAL;
                goto out;
        }
@@ -1810,7 +1812,6 @@ int drm_mode_getfb(struct drm_device *dev,
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
        if (!obj) {
-               DRM_ERROR("invalid framebuffer id\n");
                ret = -EINVAL;
                goto out;
        }
@@ -1821,7 +1822,17 @@ int drm_mode_getfb(struct drm_device *dev,
        r->depth = fb->depth;
        r->bpp = fb->bits_per_pixel;
        r->pitch = fb->pitch;
-       fb->funcs->create_handle(fb, file_priv, &r->handle);
+       if (file_priv->is_master || capable(CAP_SYS_ADMIN)) {
+               ret = fb->funcs->create_handle(fb, file_priv, &r->handle);
+       } else {
+               /* GET_FB() is an unprivileged ioctl so we must not
+                * return a buffer-handle to non-master processes! For
+                * backwards-compatibility reasons, we cannot make
+                * GET_FB() privileged, so just return an invalid handle
+                * for non-masters. */
+               r->handle = 0;
+               ret = 0;
+       }
 
 out:
        mutex_unlock(&dev->mode_config.mutex);
@@ -1846,7 +1857,6 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
        if (!obj) {
-               DRM_ERROR("invalid framebuffer id\n");
                ret = -EINVAL;
                goto out_err1;
        }
@@ -1869,6 +1879,10 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
        }
 
        if (num_clips && clips_ptr) {
+               if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
+                       ret = -EINVAL;
+                       goto out_err1;
+               }
                clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
                if (!clips) {
                        ret = -ENOMEM;
@@ -2114,8 +2128,10 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
        property->num_values = num_values;
        INIT_LIST_HEAD(&property->enum_blob_list);
 
-       if (name)
+       if (name) {
                strncpy(property->name, name, DRM_PROP_NAME_LEN);
+               property->name[DRM_PROP_NAME_LEN-1] = '\0';
+       }
 
        list_add_tail(&property->head, &dev->mode_config.property_list);
        return property;
@@ -2659,6 +2675,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
        unsigned long flags;
        int ret = -EINVAL;
 
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -EINVAL;
+
        if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
            page_flip->reserved != 0)
                return -EINVAL;