--- zzzz-none-000/linux-3.10.107/drivers/gpu/drm/cirrus/cirrus_main.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/gpu/drm/cirrus/cirrus_main.c 2021-02-04 17:41:59.000000000 +0000 @@ -49,14 +49,16 @@ struct drm_file *filp, struct drm_mode_fb_cmd2 *mode_cmd) { + struct cirrus_device *cdev = dev->dev_private; struct drm_gem_object *obj; struct cirrus_framebuffer *cirrus_fb; int ret; u32 bpp, depth; drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); - /* cirrus can't handle > 24bpp framebuffers at all */ - if (bpp > 24) + + if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height, + bpp, mode_cmd->pitches[0])) return ERR_PTR(-EINVAL); obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]); @@ -96,8 +98,7 @@ { /* BAR 0 is VRAM */ cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0); - /* We have 4MB of VRAM */ - cdev->mc.vram_size = 4 * 1024 * 1024; + cdev->mc.vram_size = pci_resource_len(cdev->dev->pdev, 0); if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size, "cirrusdrmfb_vram")) { @@ -179,17 +180,22 @@ } r = cirrus_mm_init(cdev); - if (r) + if (r) { dev_err(&dev->pdev->dev, "fatal err on mm init\n"); + goto out; + } r = cirrus_modeset_init(cdev); - if (r) + if (r) { dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r); + goto out; + } dev->mode_config.funcs = (void *)&cirrus_mode_funcs; + + return 0; out: - if (r) - cirrus_driver_unload(dev); + cirrus_driver_unload(dev); return r; } @@ -255,20 +261,7 @@ return 0; } -int cirrus_dumb_destroy(struct drm_file *file, - struct drm_device *dev, - uint32_t handle) -{ - return drm_gem_handle_delete(file, handle); -} - -int cirrus_gem_init_object(struct drm_gem_object *obj) -{ - BUG(); - return 0; -} - -void cirrus_bo_unref(struct cirrus_bo **bo) +static void cirrus_bo_unref(struct cirrus_bo **bo) { struct ttm_buffer_object *tbo; @@ -277,24 +270,20 @@ tbo = &((*bo)->bo); ttm_bo_unref(&tbo); - if (tbo == NULL) - *bo = NULL; - + *bo = NULL; } void cirrus_gem_free_object(struct drm_gem_object *obj) { struct cirrus_bo *cirrus_bo = gem_to_cirrus_bo(obj); - if (!cirrus_bo) - return; cirrus_bo_unref(&cirrus_bo); } static inline u64 cirrus_bo_mmap_offset(struct cirrus_bo *bo) { - return bo->bo.addr_space_offset; + return drm_vma_node_offset_addr(&bo->bo.vma_node); } int @@ -304,23 +293,36 @@ uint64_t *offset) { struct drm_gem_object *obj; - int ret; struct cirrus_bo *bo; - mutex_lock(&dev->struct_mutex); obj = drm_gem_object_lookup(dev, file, handle); - if (obj == NULL) { - ret = -ENOENT; - goto out_unlock; - } + if (obj == NULL) + return -ENOENT; bo = gem_to_cirrus_bo(obj); *offset = cirrus_bo_mmap_offset(bo); - drm_gem_object_unreference(obj); - ret = 0; -out_unlock: - mutex_unlock(&dev->struct_mutex); - return ret; + drm_gem_object_unreference_unlocked(obj); + + return 0; +} + +bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height, + int bpp, int pitch) +{ + const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */ + const int max_size = cdev->mc.vram_size; + + if (bpp > cirrus_bpp) + return false; + if (bpp > 32) + return false; + + if (pitch > max_pitch) + return false; + + if (pitch * height > max_size) + return false; + return true; }