diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 30 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 365 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_evict.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_execbuffer.c | 130 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 12 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_cs.c | 21 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_vm.c | 6 |
12 files changed, 298 insertions, 304 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 96177eec0a0e..eedb023af27d 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -1833,7 +1833,6 @@ int i915_driver_unload(struct drm_device *dev) | |||
| 1833 | flush_workqueue(dev_priv->wq); | 1833 | flush_workqueue(dev_priv->wq); |
| 1834 | 1834 | ||
| 1835 | mutex_lock(&dev->struct_mutex); | 1835 | mutex_lock(&dev->struct_mutex); |
| 1836 | i915_gem_free_all_phys_object(dev); | ||
| 1837 | i915_gem_cleanup_ringbuffer(dev); | 1836 | i915_gem_cleanup_ringbuffer(dev); |
| 1838 | i915_gem_context_fini(dev); | 1837 | i915_gem_context_fini(dev); |
| 1839 | WARN_ON(dev_priv->mm.aliasing_ppgtt); | 1838 | WARN_ON(dev_priv->mm.aliasing_ppgtt); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 108e1ec2fa4b..388c028e223c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -242,18 +242,6 @@ struct intel_ddi_plls { | |||
| 242 | #define WATCH_LISTS 0 | 242 | #define WATCH_LISTS 0 |
| 243 | #define WATCH_GTT 0 | 243 | #define WATCH_GTT 0 |
| 244 | 244 | ||
| 245 | #define I915_GEM_PHYS_CURSOR_0 1 | ||
| 246 | #define I915_GEM_PHYS_CURSOR_1 2 | ||
| 247 | #define I915_GEM_PHYS_OVERLAY_REGS 3 | ||
| 248 | #define I915_MAX_PHYS_OBJECT (I915_GEM_PHYS_OVERLAY_REGS) | ||
| 249 | |||
| 250 | struct drm_i915_gem_phys_object { | ||
| 251 | int id; | ||
| 252 | struct page **page_list; | ||
| 253 | drm_dma_handle_t *handle; | ||
| 254 | struct drm_i915_gem_object *cur_obj; | ||
| 255 | }; | ||
| 256 | |||
| 257 | struct opregion_header; | 245 | struct opregion_header; |
| 258 | struct opregion_acpi; | 246 | struct opregion_acpi; |
| 259 | struct opregion_swsci; | 247 | struct opregion_swsci; |
| @@ -1187,9 +1175,6 @@ struct i915_gem_mm { | |||
| 1187 | /** Bit 6 swizzling required for Y tiling */ | 1175 | /** Bit 6 swizzling required for Y tiling */ |
| 1188 | uint32_t bit_6_swizzle_y; | 1176 | uint32_t bit_6_swizzle_y; |
| 1189 | 1177 | ||
| 1190 | /* storage for physical objects */ | ||
| 1191 | struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; | ||
| 1192 | |||
| 1193 | /* accounting, useful for userland debugging */ | 1178 | /* accounting, useful for userland debugging */ |
| 1194 | spinlock_t object_stat_lock; | 1179 | spinlock_t object_stat_lock; |
| 1195 | size_t object_memory; | 1180 | size_t object_memory; |
| @@ -1769,7 +1754,7 @@ struct drm_i915_gem_object { | |||
| 1769 | struct drm_file *pin_filp; | 1754 | struct drm_file *pin_filp; |
| 1770 | 1755 | ||
| 1771 | /** for phy allocated objects */ | 1756 | /** for phy allocated objects */ |
| 1772 | struct drm_i915_gem_phys_object *phys_obj; | 1757 | drm_dma_handle_t *phys_handle; |
| 1773 | }; | 1758 | }; |
| 1774 | 1759 | ||
| 1775 | #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base) | 1760 | #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base) |
| @@ -2204,10 +2189,12 @@ void i915_gem_vma_destroy(struct i915_vma *vma); | |||
| 2204 | #define PIN_MAPPABLE 0x1 | 2189 | #define PIN_MAPPABLE 0x1 |
| 2205 | #define PIN_NONBLOCK 0x2 | 2190 | #define PIN_NONBLOCK 0x2 |
| 2206 | #define PIN_GLOBAL 0x4 | 2191 | #define PIN_GLOBAL 0x4 |
| 2192 | #define PIN_OFFSET_BIAS 0x8 | ||
| 2193 | #define PIN_OFFSET_MASK (~4095) | ||
| 2207 | int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, | 2194 | int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, |
| 2208 | struct i915_address_space *vm, | 2195 | struct i915_address_space *vm, |
| 2209 | uint32_t alignment, | 2196 | uint32_t alignment, |
| 2210 | unsigned flags); | 2197 | uint64_t flags); |
| 2211 | int __must_check i915_vma_unbind(struct i915_vma *vma); | 2198 | int __must_check i915_vma_unbind(struct i915_vma *vma); |
| 2212 | int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); | 2199 | int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); |
| 2213 | void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); | 2200 | void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); |
| @@ -2334,13 +2321,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, | |||
| 2334 | u32 alignment, | 2321 | u32 alignment, |
| 2335 | struct intel_ring_buffer *pipelined); | 2322 | struct intel_ring_buffer *pipelined); |
| 2336 | void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj); | 2323 | void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj); |
| 2337 | int i915_gem_attach_phys_object(struct drm_device *dev, | 2324 | int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, |
| 2338 | struct drm_i915_gem_object *obj, | ||
| 2339 | int id, | ||
| 2340 | int align); | 2325 | int align); |
| 2341 | void i915_gem_detach_phys_object(struct drm_device *dev, | ||
| 2342 | struct drm_i915_gem_object *obj); | ||
| 2343 | void i915_gem_free_all_phys_object(struct drm_device *dev); | ||
| 2344 | int i915_gem_open(struct drm_device *dev, struct drm_file *file); | 2326 | int i915_gem_open(struct drm_device *dev, struct drm_file *file); |
| 2345 | void i915_gem_release(struct drm_device *dev, struct drm_file *file); | 2327 | void i915_gem_release(struct drm_device *dev, struct drm_file *file); |
| 2346 | 2328 | ||
| @@ -2465,6 +2447,8 @@ int __must_check i915_gem_evict_something(struct drm_device *dev, | |||
| 2465 | int min_size, | 2447 | int min_size, |
| 2466 | unsigned alignment, | 2448 | unsigned alignment, |
| 2467 | unsigned cache_level, | 2449 | unsigned cache_level, |
| 2450 | unsigned long start, | ||
| 2451 | unsigned long end, | ||
| 2468 | unsigned flags); | 2452 | unsigned flags); |
| 2469 | int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle); | 2453 | int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle); |
| 2470 | int i915_gem_evict_everything(struct drm_device *dev); | 2454 | int i915_gem_evict_everything(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2871ce75f438..3326770c9ed2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -43,10 +43,6 @@ static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *o | |||
| 43 | static __must_check int | 43 | static __must_check int |
| 44 | i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, | 44 | i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, |
| 45 | bool readonly); | 45 | bool readonly); |
| 46 | static int i915_gem_phys_pwrite(struct drm_device *dev, | ||
| 47 | struct drm_i915_gem_object *obj, | ||
| 48 | struct drm_i915_gem_pwrite *args, | ||
| 49 | struct drm_file *file); | ||
| 50 | 46 | ||
| 51 | static void i915_gem_write_fence(struct drm_device *dev, int reg, | 47 | static void i915_gem_write_fence(struct drm_device *dev, int reg, |
| 52 | struct drm_i915_gem_object *obj); | 48 | struct drm_i915_gem_object *obj); |
| @@ -209,6 +205,128 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | |||
| 209 | return 0; | 205 | return 0; |
| 210 | } | 206 | } |
| 211 | 207 | ||
| 208 | static void i915_gem_object_detach_phys(struct drm_i915_gem_object *obj) | ||
| 209 | { | ||
| 210 | drm_dma_handle_t *phys = obj->phys_handle; | ||
| 211 | |||
| 212 | if (!phys) | ||
| 213 | return; | ||
| 214 | |||
| 215 | if (obj->madv == I915_MADV_WILLNEED) { | ||
| 216 | struct address_space *mapping = file_inode(obj->base.filp)->i_mapping; | ||
| 217 | char *vaddr = phys->vaddr; | ||
| 218 | int i; | ||
| 219 | |||
| 220 | for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { | ||
| 221 | struct page *page = shmem_read_mapping_page(mapping, i); | ||
| 222 | if (!IS_ERR(page)) { | ||
| 223 | char *dst = kmap_atomic(page); | ||
| 224 | memcpy(dst, vaddr, PAGE_SIZE); | ||
| 225 | drm_clflush_virt_range(dst, PAGE_SIZE); | ||
| 226 | kunmap_atomic(dst); | ||
| 227 | |||
| 228 | set_page_dirty(page); | ||
| 229 | mark_page_accessed(page); | ||
| 230 | page_cache_release(page); | ||
| 231 | } | ||
| 232 | vaddr += PAGE_SIZE; | ||
| 233 | } | ||
| 234 | i915_gem_chipset_flush(obj->base.dev); | ||
| 235 | } | ||
| 236 | |||
| 237 | #ifdef CONFIG_X86 | ||
| 238 | set_memory_wb((unsigned long)phys->vaddr, phys->size / PAGE_SIZE); | ||
| 239 | #endif | ||
| 240 | drm_pci_free(obj->base.dev, phys); | ||
| 241 | obj->phys_handle = NULL; | ||
| 242 | } | ||
| 243 | |||
| 244 | int | ||
| 245 | i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, | ||
| 246 | int align) | ||
| 247 | { | ||
| 248 | drm_dma_handle_t *phys; | ||
| 249 | struct address_space *mapping; | ||
| 250 | char *vaddr; | ||
| 251 | int i; | ||
| 252 | |||
| 253 | if (obj->phys_handle) { | ||
| 254 | if ((unsigned long)obj->phys_handle->vaddr & (align -1)) | ||
| 255 | return -EBUSY; | ||
| 256 | |||
| 257 | return 0; | ||
| 258 | } | ||
| 259 | |||
| 260 | if (obj->madv != I915_MADV_WILLNEED) | ||
| 261 | return -EFAULT; | ||
| 262 | |||
| 263 | if (obj->base.filp == NULL) | ||
| 264 | return -EINVAL; | ||
| 265 | |||
| 266 | /* create a new object */ | ||
| 267 | phys = drm_pci_alloc(obj->base.dev, obj->base.size, align); | ||
| 268 | if (!phys) | ||
| 269 | return -ENOMEM; | ||
| 270 | |||
| 271 | vaddr = phys->vaddr; | ||
| 272 | #ifdef CONFIG_X86 | ||
| 273 | set_memory_wc((unsigned long)vaddr, phys->size / PAGE_SIZE); | ||
| 274 | #endif | ||
| 275 | mapping = file_inode(obj->base.filp)->i_mapping; | ||
| 276 | for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { | ||
| 277 | struct page *page; | ||
| 278 | char *src; | ||
| 279 | |||
| 280 | page = shmem_read_mapping_page(mapping, i); | ||
| 281 | if (IS_ERR(page)) { | ||
| 282 | #ifdef CONFIG_X86 | ||
| 283 | set_memory_wb((unsigned long)phys->vaddr, phys->size / PAGE_SIZE); | ||
| 284 | #endif | ||
| 285 | drm_pci_free(obj->base.dev, phys); | ||
| 286 | return PTR_ERR(page); | ||
| 287 | } | ||
| 288 | |||
| 289 | src = kmap_atomic(page); | ||
| 290 | memcpy(vaddr, src, PAGE_SIZE); | ||
| 291 | kunmap_atomic(src); | ||
| 292 | |||
| 293 | mark_page_accessed(page); | ||
| 294 | page_cache_release(page); | ||
| 295 | |||
| 296 | vaddr += PAGE_SIZE; | ||
| 297 | } | ||
| 298 | |||
| 299 | obj->phys_handle = phys; | ||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int | ||
| 304 | i915_gem_phys_pwrite(struct drm_i915_gem_object *obj, | ||
| 305 | struct drm_i915_gem_pwrite *args, | ||
| 306 | struct drm_file *file_priv) | ||
| 307 | { | ||
| 308 | struct drm_device *dev = obj->base.dev; | ||
| 309 | void *vaddr = obj->phys_handle->vaddr + args->offset; | ||
| 310 | char __user *user_data = to_user_ptr(args->data_ptr); | ||
| 311 | |||
| 312 | if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) { | ||
| 313 | unsigned long unwritten; | ||
| 314 | |||
| 315 | /* The physical object once assigned is fixed for the lifetime | ||
| 316 | * of the obj, so we can safely drop the lock and continue | ||
| 317 | * to access vaddr. | ||
| 318 | */ | ||
| 319 | mutex_unlock(&dev->struct_mutex); | ||
| 320 | unwritten = copy_from_user(vaddr, user_data, args->size); | ||
| 321 | mutex_lock(&dev->struct_mutex); | ||
| 322 | if (unwritten) | ||
| 323 | return -EFAULT; | ||
| 324 | } | ||
| 325 | |||
| 326 | i915_gem_chipset_flush(dev); | ||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 212 | void *i915_gem_object_alloc(struct drm_device *dev) | 330 | void *i915_gem_object_alloc(struct drm_device *dev) |
| 213 | { | 331 | { |
| 214 | struct drm_i915_private *dev_priv = dev->dev_private; | 332 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -921,8 +1039,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
| 921 | * pread/pwrite currently are reading and writing from the CPU | 1039 | * pread/pwrite currently are reading and writing from the CPU |
| 922 | * perspective, requiring manual detiling by the client. | 1040 | * perspective, requiring manual detiling by the client. |
| 923 | */ | 1041 | */ |
| 924 | if (obj->phys_obj) { | 1042 | if (obj->phys_handle) { |
| 925 | ret = i915_gem_phys_pwrite(dev, obj, args, file); | 1043 | ret = i915_gem_phys_pwrite(obj, args, file); |
| 926 | goto out; | 1044 | goto out; |
| 927 | } | 1045 | } |
| 928 | 1046 | ||
| @@ -3208,12 +3326,14 @@ static struct i915_vma * | |||
| 3208 | i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, | 3326 | i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, |
| 3209 | struct i915_address_space *vm, | 3327 | struct i915_address_space *vm, |
| 3210 | unsigned alignment, | 3328 | unsigned alignment, |
| 3211 | unsigned flags) | 3329 | uint64_t flags) |
| 3212 | { | 3330 | { |
| 3213 | struct drm_device *dev = obj->base.dev; | 3331 | struct drm_device *dev = obj->base.dev; |
| 3214 | struct drm_i915_private *dev_priv = dev->dev_private; | 3332 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3215 | u32 size, fence_size, fence_alignment, unfenced_alignment; | 3333 | u32 size, fence_size, fence_alignment, unfenced_alignment; |
| 3216 | size_t gtt_max = | 3334 | unsigned long start = |
| 3335 | flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0; | ||
| 3336 | unsigned long end = | ||
| 3217 | flags & PIN_MAPPABLE ? dev_priv->gtt.mappable_end : vm->total; | 3337 | flags & PIN_MAPPABLE ? dev_priv->gtt.mappable_end : vm->total; |
| 3218 | struct i915_vma *vma; | 3338 | struct i915_vma *vma; |
| 3219 | int ret; | 3339 | int ret; |
| @@ -3242,11 +3362,11 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, | |||
| 3242 | /* If the object is bigger than the entire aperture, reject it early | 3362 | /* If the object is bigger than the entire aperture, reject it early |
| 3243 | * before evicting everything in a vain attempt to find space. | 3363 | * before evicting everything in a vain attempt to find space. |
| 3244 | */ | 3364 | */ |
| 3245 | if (obj->base.size > gtt_max) { | 3365 | if (obj->base.size > end) { |
| 3246 | DRM_DEBUG("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n", | 3366 | DRM_DEBUG("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%lu\n", |
| 3247 | obj->base.size, | 3367 | obj->base.size, |
| 3248 | flags & PIN_MAPPABLE ? "mappable" : "total", | 3368 | flags & PIN_MAPPABLE ? "mappable" : "total", |
| 3249 | gtt_max); | 3369 | end); |
| 3250 | return ERR_PTR(-E2BIG); | 3370 | return ERR_PTR(-E2BIG); |
| 3251 | } | 3371 | } |
| 3252 | 3372 | ||
| @@ -3263,12 +3383,15 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, | |||
| 3263 | search_free: | 3383 | search_free: |
| 3264 | ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node, | 3384 | ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node, |
| 3265 | size, alignment, | 3385 | size, alignment, |
| 3266 | obj->cache_level, 0, gtt_max, | 3386 | obj->cache_level, |
| 3387 | start, end, | ||
| 3267 | DRM_MM_SEARCH_DEFAULT, | 3388 | DRM_MM_SEARCH_DEFAULT, |
| 3268 | DRM_MM_CREATE_DEFAULT); | 3389 | DRM_MM_CREATE_DEFAULT); |
| 3269 | if (ret) { | 3390 | if (ret) { |
| 3270 | ret = i915_gem_evict_something(dev, vm, size, alignment, | 3391 | ret = i915_gem_evict_something(dev, vm, size, alignment, |
| 3271 | obj->cache_level, flags); | 3392 | obj->cache_level, |
| 3393 | start, end, | ||
| 3394 | flags); | ||
| 3272 | if (ret == 0) | 3395 | if (ret == 0) |
| 3273 | goto search_free; | 3396 | goto search_free; |
| 3274 | 3397 | ||
| @@ -3828,11 +3951,30 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) | |||
| 3828 | return ret; | 3951 | return ret; |
| 3829 | } | 3952 | } |
| 3830 | 3953 | ||
| 3954 | static bool | ||
| 3955 | i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags) | ||
| 3956 | { | ||
| 3957 | struct drm_i915_gem_object *obj = vma->obj; | ||
| 3958 | |||
| 3959 | if (alignment && | ||
| 3960 | vma->node.start & (alignment - 1)) | ||
| 3961 | return true; | ||
| 3962 | |||
| 3963 | if (flags & PIN_MAPPABLE && !obj->map_and_fenceable) | ||
| 3964 | return true; | ||
| 3965 | |||
| 3966 | if (flags & PIN_OFFSET_BIAS && | ||
| 3967 | vma->node.start < (flags & PIN_OFFSET_MASK)) | ||
| 3968 | return true; | ||
| 3969 | |||
| 3970 | return false; | ||
| 3971 | } | ||
| 3972 | |||
| 3831 | int | 3973 | int |
| 3832 | i915_gem_object_pin(struct drm_i915_gem_object *obj, | 3974 | i915_gem_object_pin(struct drm_i915_gem_object *obj, |
| 3833 | struct i915_address_space *vm, | 3975 | struct i915_address_space *vm, |
| 3834 | uint32_t alignment, | 3976 | uint32_t alignment, |
| 3835 | unsigned flags) | 3977 | uint64_t flags) |
| 3836 | { | 3978 | { |
| 3837 | struct i915_vma *vma; | 3979 | struct i915_vma *vma; |
| 3838 | int ret; | 3980 | int ret; |
| @@ -3845,15 +3987,13 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, | |||
| 3845 | if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) | 3987 | if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) |
| 3846 | return -EBUSY; | 3988 | return -EBUSY; |
| 3847 | 3989 | ||
| 3848 | if ((alignment && | 3990 | if (i915_vma_misplaced(vma, alignment, flags)) { |
| 3849 | vma->node.start & (alignment - 1)) || | ||
| 3850 | (flags & PIN_MAPPABLE && !obj->map_and_fenceable)) { | ||
| 3851 | WARN(vma->pin_count, | 3991 | WARN(vma->pin_count, |
| 3852 | "bo is already pinned with incorrect alignment:" | 3992 | "bo is already pinned with incorrect alignment:" |
| 3853 | " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d," | 3993 | " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d," |
| 3854 | " obj->map_and_fenceable=%d\n", | 3994 | " obj->map_and_fenceable=%d\n", |
| 3855 | i915_gem_obj_offset(obj, vm), alignment, | 3995 | i915_gem_obj_offset(obj, vm), alignment, |
| 3856 | flags & PIN_MAPPABLE, | 3996 | !!(flags & PIN_MAPPABLE), |
| 3857 | obj->map_and_fenceable); | 3997 | obj->map_and_fenceable); |
| 3858 | ret = i915_vma_unbind(vma); | 3998 | ret = i915_vma_unbind(vma); |
| 3859 | if (ret) | 3999 | if (ret) |
| @@ -4163,9 +4303,6 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) | |||
| 4163 | 4303 | ||
| 4164 | trace_i915_gem_object_destroy(obj); | 4304 | trace_i915_gem_object_destroy(obj); |
| 4165 | 4305 | ||
| 4166 | if (obj->phys_obj) | ||
| 4167 | i915_gem_detach_phys_object(dev, obj); | ||
| 4168 | |||
| 4169 | list_for_each_entry_safe(vma, next, &obj->vma_list, vma_link) { | 4306 | list_for_each_entry_safe(vma, next, &obj->vma_list, vma_link) { |
| 4170 | int ret; | 4307 | int ret; |
| 4171 | 4308 | ||
| @@ -4183,6 +4320,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) | |||
| 4183 | } | 4320 | } |
| 4184 | } | 4321 | } |
| 4185 | 4322 | ||
| 4323 | i915_gem_object_detach_phys(obj); | ||
| 4324 | |||
| 4186 | /* Stolen objects don't hold a ref, but do hold pin count. Fix that up | 4325 | /* Stolen objects don't hold a ref, but do hold pin count. Fix that up |
| 4187 | * before progressing. */ | 4326 | * before progressing. */ |
| 4188 | if (obj->stolen) | 4327 | if (obj->stolen) |
| @@ -4646,190 +4785,6 @@ i915_gem_load(struct drm_device *dev) | |||
| 4646 | register_shrinker(&dev_priv->mm.inactive_shrinker); | 4785 | register_shrinker(&dev_priv->mm.inactive_shrinker); |
| 4647 | } | 4786 | } |
| 4648 | 4787 | ||
| 4649 | /* | ||
| 4650 | * Create a physically contiguous memory object for this object | ||
| 4651 | * e.g. for cursor + overlay regs | ||
| 4652 | */ | ||
| 4653 | static int i915_gem_init_phys_object(struct drm_device *dev, | ||
| 4654 | int id, int size, int align) | ||
| 4655 | { | ||
| 4656 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 4657 | struct drm_i915_gem_phys_object *phys_obj; | ||
| 4658 | int ret; | ||
| 4659 | |||
| 4660 | if (dev_priv->mm.phys_objs[id - 1] || !size) | ||
| 4661 | return 0; | ||
| 4662 | |||
| 4663 | phys_obj = kzalloc(sizeof(*phys_obj), GFP_KERNEL); | ||
| 4664 | if (!phys_obj) | ||
| 4665 | return -ENOMEM; | ||
| 4666 | |||
| 4667 | phys_obj->id = id; | ||
| 4668 | |||
| 4669 | phys_obj->handle = drm_pci_alloc(dev, size, align); | ||
| 4670 | if (!phys_obj->handle) { | ||
| 4671 | ret = -ENOMEM; | ||
| 4672 | goto kfree_obj; | ||
| 4673 | } | ||
| 4674 | #ifdef CONFIG_X86 | ||
| 4675 | set_memory_wc((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE); | ||
| 4676 | #endif | ||
| 4677 | |||
| 4678 | dev_priv->mm.phys_objs[id - 1] = phys_obj; | ||
| 4679 | |||
| 4680 | return 0; | ||
| 4681 | kfree_obj: | ||
| 4682 | kfree(phys_obj); | ||
| 4683 | return ret; | ||
| 4684 | } | ||
| 4685 | |||
| 4686 | static void i915_gem_free_phys_object(struct drm_device *dev, int id) | ||
| 4687 | { | ||
| 4688 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 4689 | struct drm_i915_gem_phys_object *phys_obj; | ||
| 4690 | |||
| 4691 | if (!dev_priv->mm.phys_objs[id - 1]) | ||
| 4692 | return; | ||
| 4693 | |||
| 4694 | phys_obj = dev_priv->mm.phys_objs[id - 1]; | ||
| 4695 | if (phys_obj->cur_obj) { | ||
| 4696 | i915_gem_detach_phys_object(dev, phys_obj->cur_obj); | ||
| 4697 | } | ||
| 4698 | |||
| 4699 | #ifdef CONFIG_X86 | ||
| 4700 | set_memory_wb((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE); | ||
| 4701 | #endif | ||
| 4702 | drm_pci_free(dev, phys_obj->handle); | ||
| 4703 | kfree(phys_obj); | ||
| 4704 | dev_priv->mm.phys_objs[id - 1] = NULL; | ||
| 4705 | } | ||
| 4706 | |||
| 4707 | void i915_gem_free_all_phys_object(struct drm_device *dev) | ||
| 4708 | { | ||
| 4709 | int i; | ||
| 4710 | |||
| 4711 | for (i = I915_GEM_PHYS_CURSOR_0; i <= I915_MAX_PHYS_OBJECT; i++) | ||
| 4712 | i915_gem_free_phys_object(dev, i); | ||
| 4713 | } | ||
| 4714 | |||
| 4715 | void i915_gem_detach_phys_object(struct drm_device *dev, | ||
| 4716 | struct drm_i915_gem_object *obj) | ||
| 4717 | { | ||
| 4718 | struct address_space *mapping = file_inode(obj->base.filp)->i_mapping; | ||
| 4719 | char *vaddr; | ||
| 4720 | int i; | ||
| 4721 | int page_count; | ||
| 4722 | |||
| 4723 | if (!obj->phys_obj) | ||
| 4724 | return; | ||
| 4725 | vaddr = obj->phys_obj->handle->vaddr; | ||
| 4726 | |||
| 4727 | page_count = obj->base.size / PAGE_SIZE; | ||
| 4728 | for (i = 0; i < page_count; i++) { | ||
| 4729 | struct page *page = shmem_read_mapping_page(mapping, i); | ||
| 4730 | if (!IS_ERR(page)) { | ||
| 4731 | char *dst = kmap_atomic(page); | ||
| 4732 | memcpy(dst, vaddr + i*PAGE_SIZE, PAGE_SIZE); | ||
| 4733 | kunmap_atomic(dst); | ||
| 4734 | |||
| 4735 | drm_clflush_pages(&page, 1); | ||
| 4736 | |||
| 4737 | set_page_dirty(page); | ||
| 4738 | mark_page_accessed(page); | ||
| 4739 | page_cache_release(page); | ||
| 4740 | } | ||
| 4741 | } | ||
| 4742 | i915_gem_chipset_flush(dev); | ||
| 4743 | |||
| 4744 | obj->phys_obj->cur_obj = NULL; | ||
| 4745 | obj->phys_obj = NULL; | ||
| 4746 | } | ||
| 4747 | |||
| 4748 | int | ||
| 4749 | i915_gem_attach_phys_object(struct drm_device *dev, | ||
| 4750 | struct drm_i915_gem_object *obj, | ||
| 4751 | int id, | ||
| 4752 | int align) | ||
| 4753 | { | ||
| 4754 | struct address_space *mapping = file_inode(obj->base.filp)->i_mapping; | ||
| 4755 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 4756 | int ret = 0; | ||
| 4757 | int page_count; | ||
| 4758 | int i; | ||
| 4759 | |||
| 4760 | if (id > I915_MAX_PHYS_OBJECT) | ||
| 4761 | return -EINVAL; | ||
| 4762 | |||
| 4763 | if (obj->phys_obj) { | ||
| 4764 | if (obj->phys_obj->id == id) | ||
| 4765 | return 0; | ||
| 4766 | i915_gem_detach_phys_object(dev, obj); | ||
| 4767 | } | ||
| 4768 | |||
| 4769 | /* create a new object */ | ||
| 4770 | if (!dev_priv->mm.phys_objs[id - 1]) { | ||
| 4771 | ret = i915_gem_init_phys_object(dev, id, | ||
| 4772 | obj->base.size, align); | ||
| 4773 | if (ret) { | ||
| 4774 | DRM_ERROR("failed to init phys object %d size: %zu\n", | ||
| 4775 | id, obj->base.size); | ||
| 4776 | return ret; | ||
| 4777 | } | ||
| 4778 | } | ||
| 4779 | |||
| 4780 | /* bind to the object */ | ||
| 4781 | obj->phys_obj = dev_priv->mm.phys_objs[id - 1]; | ||
| 4782 | obj->phys_obj->cur_obj = obj; | ||
| 4783 | |||
| 4784 | page_count = obj->base.size / PAGE_SIZE; | ||
| 4785 | |||
| 4786 | for (i = 0; i < page_count; i++) { | ||
| 4787 | struct page *page; | ||
| 4788 | char *dst, *src; | ||
| 4789 | |||
| 4790 | page = shmem_read_mapping_page(mapping, i); | ||
| 4791 | if (IS_ERR(page)) | ||
| 4792 | return PTR_ERR(page); | ||
| 4793 | |||
| 4794 | src = kmap_atomic(page); | ||
| 4795 | dst = obj->phys_obj->handle->vaddr + (i * PAGE_SIZE); | ||
| 4796 | memcpy(dst, src, PAGE_SIZE); | ||
| 4797 | kunmap_atomic(src); | ||
| 4798 | |||
| 4799 | mark_page_accessed(page); | ||
| 4800 | page_cache_release(page); | ||
| 4801 | } | ||
| 4802 | |||
| 4803 | return 0; | ||
| 4804 | } | ||
| 4805 | |||
| 4806 | static int | ||
| 4807 | i915_gem_phys_pwrite(struct drm_device *dev, | ||
| 4808 | struct drm_i915_gem_object *obj, | ||
| 4809 | struct drm_i915_gem_pwrite *args, | ||
| 4810 | struct drm_file *file_priv) | ||
| 4811 | { | ||
| 4812 | void *vaddr = obj->phys_obj->handle->vaddr + args->offset; | ||
| 4813 | char __user *user_data = to_user_ptr(args->data_ptr); | ||
| 4814 | |||
| 4815 | if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) { | ||
| 4816 | unsigned long unwritten; | ||
| 4817 | |||
| 4818 | /* The physical object once assigned is fixed for the lifetime | ||
| 4819 | * of the obj, so we can safely drop the lock and continue | ||
| 4820 | * to access vaddr. | ||
| 4821 | */ | ||
| 4822 | mutex_unlock(&dev->struct_mutex); | ||
| 4823 | unwritten = copy_from_user(vaddr, user_data, args->size); | ||
| 4824 | mutex_lock(&dev->struct_mutex); | ||
| 4825 | if (unwritten) | ||
| 4826 | return -EFAULT; | ||
| 4827 | } | ||
| 4828 | |||
| 4829 | i915_gem_chipset_flush(dev); | ||
| 4830 | return 0; | ||
| 4831 | } | ||
| 4832 | |||
| 4833 | void i915_gem_release(struct drm_device *dev, struct drm_file *file) | 4788 | void i915_gem_release(struct drm_device *dev, struct drm_file *file) |
| 4834 | { | 4789 | { |
| 4835 | struct drm_i915_file_private *file_priv = file->driver_priv; | 4790 | struct drm_i915_file_private *file_priv = file->driver_priv; |
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 75fca63dc8c1..bbf4b12d842e 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
| @@ -68,9 +68,9 @@ mark_free(struct i915_vma *vma, struct list_head *unwind) | |||
| 68 | int | 68 | int |
| 69 | i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, | 69 | i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, |
| 70 | int min_size, unsigned alignment, unsigned cache_level, | 70 | int min_size, unsigned alignment, unsigned cache_level, |
| 71 | unsigned long start, unsigned long end, | ||
| 71 | unsigned flags) | 72 | unsigned flags) |
| 72 | { | 73 | { |
| 73 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 74 | struct list_head eviction_list, unwind_list; | 74 | struct list_head eviction_list, unwind_list; |
| 75 | struct i915_vma *vma; | 75 | struct i915_vma *vma; |
| 76 | int ret = 0; | 76 | int ret = 0; |
| @@ -102,11 +102,10 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, | |||
| 102 | */ | 102 | */ |
| 103 | 103 | ||
| 104 | INIT_LIST_HEAD(&unwind_list); | 104 | INIT_LIST_HEAD(&unwind_list); |
| 105 | if (flags & PIN_MAPPABLE) { | 105 | if (start != 0 || end != vm->total) { |
| 106 | BUG_ON(!i915_is_ggtt(vm)); | ||
| 107 | drm_mm_init_scan_with_range(&vm->mm, min_size, | 106 | drm_mm_init_scan_with_range(&vm->mm, min_size, |
| 108 | alignment, cache_level, 0, | 107 | alignment, cache_level, |
| 109 | dev_priv->gtt.mappable_end); | 108 | start, end); |
| 110 | } else | 109 | } else |
| 111 | drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level); | 110 | drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level); |
| 112 | 111 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 2c9d9cbaf653..20fef6c50267 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
| @@ -35,6 +35,9 @@ | |||
| 35 | 35 | ||
| 36 | #define __EXEC_OBJECT_HAS_PIN (1<<31) | 36 | #define __EXEC_OBJECT_HAS_PIN (1<<31) |
| 37 | #define __EXEC_OBJECT_HAS_FENCE (1<<30) | 37 | #define __EXEC_OBJECT_HAS_FENCE (1<<30) |
| 38 | #define __EXEC_OBJECT_NEEDS_BIAS (1<<28) | ||
| 39 | |||
| 40 | #define BATCH_OFFSET_BIAS (256*1024) | ||
| 38 | 41 | ||
| 39 | struct eb_vmas { | 42 | struct eb_vmas { |
| 40 | struct list_head vmas; | 43 | struct list_head vmas; |
| @@ -545,7 +548,7 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, | |||
| 545 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; | 548 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
| 546 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; | 549 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; |
| 547 | bool need_fence; | 550 | bool need_fence; |
| 548 | unsigned flags; | 551 | uint64_t flags; |
| 549 | int ret; | 552 | int ret; |
| 550 | 553 | ||
| 551 | flags = 0; | 554 | flags = 0; |
| @@ -559,6 +562,8 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, | |||
| 559 | 562 | ||
| 560 | if (entry->flags & EXEC_OBJECT_NEEDS_GTT) | 563 | if (entry->flags & EXEC_OBJECT_NEEDS_GTT) |
| 561 | flags |= PIN_GLOBAL; | 564 | flags |= PIN_GLOBAL; |
| 565 | if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) | ||
| 566 | flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS; | ||
| 562 | 567 | ||
| 563 | ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, flags); | 568 | ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, flags); |
| 564 | if (ret) | 569 | if (ret) |
| @@ -592,6 +597,36 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, | |||
| 592 | return 0; | 597 | return 0; |
| 593 | } | 598 | } |
| 594 | 599 | ||
| 600 | static bool | ||
| 601 | eb_vma_misplaced(struct i915_vma *vma, bool has_fenced_gpu_access) | ||
| 602 | { | ||
| 603 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; | ||
| 604 | struct drm_i915_gem_object *obj = vma->obj; | ||
| 605 | bool need_fence, need_mappable; | ||
| 606 | |||
| 607 | need_fence = | ||
| 608 | has_fenced_gpu_access && | ||
| 609 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && | ||
| 610 | obj->tiling_mode != I915_TILING_NONE; | ||
| 611 | need_mappable = need_fence || need_reloc_mappable(vma); | ||
| 612 | |||
| 613 | WARN_ON((need_mappable || need_fence) && | ||
| 614 | !i915_is_ggtt(vma->vm)); | ||
| 615 | |||
| 616 | if (entry->alignment && | ||
| 617 | vma->node.start & (entry->alignment - 1)) | ||
| 618 | return true; | ||
| 619 | |||
| 620 | if (need_mappable && !obj->map_and_fenceable) | ||
| 621 | return true; | ||
| 622 | |||
| 623 | if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS && | ||
| 624 | vma->node.start < BATCH_OFFSET_BIAS) | ||
| 625 | return true; | ||
| 626 | |||
| 627 | return false; | ||
| 628 | } | ||
| 629 | |||
| 595 | static int | 630 | static int |
| 596 | i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, | 631 | i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, |
| 597 | struct list_head *vmas, | 632 | struct list_head *vmas, |
| @@ -653,26 +688,10 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, | |||
| 653 | 688 | ||
| 654 | /* Unbind any ill-fitting objects or pin. */ | 689 | /* Unbind any ill-fitting objects or pin. */ |
| 655 | list_for_each_entry(vma, vmas, exec_list) { | 690 | list_for_each_entry(vma, vmas, exec_list) { |
| 656 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; | ||
| 657 | bool need_fence, need_mappable; | ||
| 658 | |||
| 659 | obj = vma->obj; | ||
| 660 | |||
| 661 | if (!drm_mm_node_allocated(&vma->node)) | 691 | if (!drm_mm_node_allocated(&vma->node)) |
| 662 | continue; | 692 | continue; |
| 663 | 693 | ||
| 664 | need_fence = | 694 | if (eb_vma_misplaced(vma, has_fenced_gpu_access)) |
| 665 | has_fenced_gpu_access && | ||
| 666 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && | ||
| 667 | obj->tiling_mode != I915_TILING_NONE; | ||
| 668 | need_mappable = need_fence || need_reloc_mappable(vma); | ||
| 669 | |||
| 670 | WARN_ON((need_mappable || need_fence) && | ||
| 671 | !i915_is_ggtt(vma->vm)); | ||
| 672 | |||
| 673 | if ((entry->alignment && | ||
| 674 | vma->node.start & (entry->alignment - 1)) || | ||
| 675 | (need_mappable && !obj->map_and_fenceable)) | ||
| 676 | ret = i915_vma_unbind(vma); | 695 | ret = i915_vma_unbind(vma); |
| 677 | else | 696 | else |
| 678 | ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); | 697 | ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); |
| @@ -773,9 +792,9 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | |||
| 773 | * relocations were valid. | 792 | * relocations were valid. |
| 774 | */ | 793 | */ |
| 775 | for (j = 0; j < exec[i].relocation_count; j++) { | 794 | for (j = 0; j < exec[i].relocation_count; j++) { |
| 776 | if (copy_to_user(&user_relocs[j].presumed_offset, | 795 | if (__copy_to_user(&user_relocs[j].presumed_offset, |
| 777 | &invalid_offset, | 796 | &invalid_offset, |
| 778 | sizeof(invalid_offset))) { | 797 | sizeof(invalid_offset))) { |
| 779 | ret = -EFAULT; | 798 | ret = -EFAULT; |
| 780 | mutex_lock(&dev->struct_mutex); | 799 | mutex_lock(&dev->struct_mutex); |
| 781 | goto err; | 800 | goto err; |
| @@ -999,6 +1018,25 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev, | |||
| 999 | return 0; | 1018 | return 0; |
| 1000 | } | 1019 | } |
| 1001 | 1020 | ||
| 1021 | static struct drm_i915_gem_object * | ||
| 1022 | eb_get_batch(struct eb_vmas *eb) | ||
| 1023 | { | ||
| 1024 | struct i915_vma *vma = list_entry(eb->vmas.prev, typeof(*vma), exec_list); | ||
| 1025 | |||
| 1026 | /* | ||
| 1027 | * SNA is doing fancy tricks with compressing batch buffers, which leads | ||
| 1028 | * to negative relocation deltas. Usually that works out ok since the | ||
| 1029 | * relocate address is still positive, except when the batch is placed | ||
| 1030 | * very low in the GTT. Ensure this doesn't happen. | ||
| 1031 | * | ||
| 1032 | * Note that actual hangs have only been observed on gen7, but for | ||
| 1033 | * paranoia do it everywhere. | ||
| 1034 | */ | ||
| 1035 | vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS; | ||
| 1036 | |||
| 1037 | return vma->obj; | ||
| 1038 | } | ||
| 1039 | |||
| 1002 | static int | 1040 | static int |
| 1003 | i915_gem_do_execbuffer(struct drm_device *dev, void *data, | 1041 | i915_gem_do_execbuffer(struct drm_device *dev, void *data, |
| 1004 | struct drm_file *file, | 1042 | struct drm_file *file, |
| @@ -1153,7 +1191,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 1153 | goto err; | 1191 | goto err; |
| 1154 | 1192 | ||
| 1155 | /* take note of the batch buffer before we might reorder the lists */ | 1193 | /* take note of the batch buffer before we might reorder the lists */ |
| 1156 | batch_obj = list_entry(eb->vmas.prev, struct i915_vma, exec_list)->obj; | 1194 | batch_obj = eb_get_batch(eb); |
| 1157 | 1195 | ||
| 1158 | /* Move the objects en-masse into the GTT, evicting if necessary. */ | 1196 | /* Move the objects en-masse into the GTT, evicting if necessary. */ |
| 1159 | need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0; | 1197 | need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0; |
| @@ -1355,18 +1393,21 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 1355 | 1393 | ||
| 1356 | ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); | 1394 | ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); |
| 1357 | if (!ret) { | 1395 | if (!ret) { |
| 1396 | struct drm_i915_gem_exec_object __user *user_exec_list = | ||
| 1397 | to_user_ptr(args->buffers_ptr); | ||
| 1398 | |||
| 1358 | /* Copy the new buffer offsets back to the user's exec list. */ | 1399 | /* Copy the new buffer offsets back to the user's exec list. */ |
| 1359 | for (i = 0; i < args->buffer_count; i++) | 1400 | for (i = 0; i < args->buffer_count; i++) { |
| 1360 | exec_list[i].offset = exec2_list[i].offset; | 1401 | ret = __copy_to_user(&user_exec_list[i].offset, |
| 1361 | /* ... and back out to userspace */ | 1402 | &exec2_list[i].offset, |
| 1362 | ret = copy_to_user(to_user_ptr(args->buffers_ptr), | 1403 | sizeof(user_exec_list[i].offset)); |
| 1363 | exec_list, | 1404 | if (ret) { |
| 1364 | sizeof(*exec_list) * args->buffer_count); | 1405 | ret = -EFAULT; |
| 1365 | if (ret) { | 1406 | DRM_DEBUG("failed to copy %d exec entries " |
| 1366 | ret = -EFAULT; | 1407 | "back to user (%d)\n", |
| 1367 | DRM_DEBUG("failed to copy %d exec entries " | 1408 | args->buffer_count, ret); |
| 1368 | "back to user (%d)\n", | 1409 | break; |
| 1369 | args->buffer_count, ret); | 1410 | } |
| 1370 | } | 1411 | } |
| 1371 | } | 1412 | } |
| 1372 | 1413 | ||
| @@ -1412,14 +1453,21 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, | |||
| 1412 | ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list); | 1453 | ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list); |
| 1413 | if (!ret) { | 1454 | if (!ret) { |
| 1414 | /* Copy the new buffer offsets back to the user's exec list. */ | 1455 | /* Copy the new buffer offsets back to the user's exec list. */ |
| 1415 | ret = copy_to_user(to_user_ptr(args->buffers_ptr), | 1456 | struct drm_i915_gem_exec_object2 *user_exec_list = |
| 1416 | exec2_list, | 1457 | to_user_ptr(args->buffers_ptr); |
| 1417 | sizeof(*exec2_list) * args->buffer_count); | 1458 | int i; |
| 1418 | if (ret) { | 1459 | |
| 1419 | ret = -EFAULT; | 1460 | for (i = 0; i < args->buffer_count; i++) { |
| 1420 | DRM_DEBUG("failed to copy %d exec entries " | 1461 | ret = __copy_to_user(&user_exec_list[i].offset, |
| 1421 | "back to user (%d)\n", | 1462 | &exec2_list[i].offset, |
| 1422 | args->buffer_count, ret); | 1463 | sizeof(user_exec_list[i].offset)); |
| 1464 | if (ret) { | ||
| 1465 | ret = -EFAULT; | ||
| 1466 | DRM_DEBUG("failed to copy %d exec entries " | ||
| 1467 | "back to user\n", | ||
| 1468 | args->buffer_count); | ||
| 1469 | break; | ||
| 1470 | } | ||
| 1423 | } | 1471 | } |
| 1424 | } | 1472 | } |
| 1425 | 1473 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 154b0f8bb88d..5deb22864c52 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
| @@ -1089,7 +1089,9 @@ alloc: | |||
| 1089 | if (ret == -ENOSPC && !retried) { | 1089 | if (ret == -ENOSPC && !retried) { |
| 1090 | ret = i915_gem_evict_something(dev, &dev_priv->gtt.base, | 1090 | ret = i915_gem_evict_something(dev, &dev_priv->gtt.base, |
| 1091 | GEN6_PD_SIZE, GEN6_PD_ALIGN, | 1091 | GEN6_PD_SIZE, GEN6_PD_ALIGN, |
| 1092 | I915_CACHE_NONE, 0); | 1092 | I915_CACHE_NONE, |
| 1093 | 0, dev_priv->gtt.base.total, | ||
| 1094 | 0); | ||
| 1093 | if (ret) | 1095 | if (ret) |
| 1094 | return ret; | 1096 | return ret; |
| 1095 | 1097 | ||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 48aa516a1ac0..5b60e25baa32 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -7825,14 +7825,12 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 7825 | addr = i915_gem_obj_ggtt_offset(obj); | 7825 | addr = i915_gem_obj_ggtt_offset(obj); |
| 7826 | } else { | 7826 | } else { |
| 7827 | int align = IS_I830(dev) ? 16 * 1024 : 256; | 7827 | int align = IS_I830(dev) ? 16 * 1024 : 256; |
| 7828 | ret = i915_gem_attach_phys_object(dev, obj, | 7828 | ret = i915_gem_object_attach_phys(obj, align); |
| 7829 | (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1, | ||
| 7830 | align); | ||
| 7831 | if (ret) { | 7829 | if (ret) { |
| 7832 | DRM_DEBUG_KMS("failed to attach phys object\n"); | 7830 | DRM_DEBUG_KMS("failed to attach phys object\n"); |
| 7833 | goto fail_locked; | 7831 | goto fail_locked; |
| 7834 | } | 7832 | } |
| 7835 | addr = obj->phys_obj->handle->busaddr; | 7833 | addr = obj->phys_handle->busaddr; |
| 7836 | } | 7834 | } |
| 7837 | 7835 | ||
| 7838 | if (IS_GEN2(dev)) | 7836 | if (IS_GEN2(dev)) |
| @@ -7840,10 +7838,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 7840 | 7838 | ||
| 7841 | finish: | 7839 | finish: |
| 7842 | if (intel_crtc->cursor_bo) { | 7840 | if (intel_crtc->cursor_bo) { |
| 7843 | if (INTEL_INFO(dev)->cursor_needs_physical) { | 7841 | if (!INTEL_INFO(dev)->cursor_needs_physical) |
| 7844 | if (intel_crtc->cursor_bo != obj) | ||
| 7845 | i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); | ||
| 7846 | } else | ||
| 7847 | i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo); | 7842 | i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo); |
| 7848 | drm_gem_object_unreference(&intel_crtc->cursor_bo->base); | 7843 | drm_gem_object_unreference(&intel_crtc->cursor_bo->base); |
| 7849 | } | 7844 | } |
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index d8adc9104dca..129db0c7d835 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
| @@ -193,7 +193,7 @@ intel_overlay_map_regs(struct intel_overlay *overlay) | |||
| 193 | struct overlay_registers __iomem *regs; | 193 | struct overlay_registers __iomem *regs; |
| 194 | 194 | ||
| 195 | if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) | 195 | if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) |
| 196 | regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_obj->handle->vaddr; | 196 | regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr; |
| 197 | else | 197 | else |
| 198 | regs = io_mapping_map_wc(dev_priv->gtt.mappable, | 198 | regs = io_mapping_map_wc(dev_priv->gtt.mappable, |
| 199 | i915_gem_obj_ggtt_offset(overlay->reg_bo)); | 199 | i915_gem_obj_ggtt_offset(overlay->reg_bo)); |
| @@ -1340,14 +1340,12 @@ void intel_setup_overlay(struct drm_device *dev) | |||
| 1340 | overlay->reg_bo = reg_bo; | 1340 | overlay->reg_bo = reg_bo; |
| 1341 | 1341 | ||
| 1342 | if (OVERLAY_NEEDS_PHYSICAL(dev)) { | 1342 | if (OVERLAY_NEEDS_PHYSICAL(dev)) { |
| 1343 | ret = i915_gem_attach_phys_object(dev, reg_bo, | 1343 | ret = i915_gem_object_attach_phys(reg_bo, PAGE_SIZE); |
| 1344 | I915_GEM_PHYS_OVERLAY_REGS, | ||
| 1345 | PAGE_SIZE); | ||
| 1346 | if (ret) { | 1344 | if (ret) { |
| 1347 | DRM_ERROR("failed to attach phys overlay regs\n"); | 1345 | DRM_ERROR("failed to attach phys overlay regs\n"); |
| 1348 | goto out_free_bo; | 1346 | goto out_free_bo; |
| 1349 | } | 1347 | } |
| 1350 | overlay->flip_addr = reg_bo->phys_obj->handle->busaddr; | 1348 | overlay->flip_addr = reg_bo->phys_handle->busaddr; |
| 1351 | } else { | 1349 | } else { |
| 1352 | ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, PIN_MAPPABLE); | 1350 | ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, PIN_MAPPABLE); |
| 1353 | if (ret) { | 1351 | if (ret) { |
| @@ -1428,7 +1426,7 @@ intel_overlay_map_regs_atomic(struct intel_overlay *overlay) | |||
| 1428 | /* Cast to make sparse happy, but it's wc memory anyway, so | 1426 | /* Cast to make sparse happy, but it's wc memory anyway, so |
| 1429 | * equivalent to the wc io mapping on X86. */ | 1427 | * equivalent to the wc io mapping on X86. */ |
| 1430 | regs = (struct overlay_registers __iomem *) | 1428 | regs = (struct overlay_registers __iomem *) |
| 1431 | overlay->reg_bo->phys_obj->handle->vaddr; | 1429 | overlay->reg_bo->phys_handle->vaddr; |
| 1432 | else | 1430 | else |
| 1433 | regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable, | 1431 | regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable, |
| 1434 | i915_gem_obj_ggtt_offset(overlay->reg_bo)); | 1432 | i915_gem_obj_ggtt_offset(overlay->reg_bo)); |
| @@ -1462,7 +1460,7 @@ intel_overlay_capture_error_state(struct drm_device *dev) | |||
| 1462 | error->dovsta = I915_READ(DOVSTA); | 1460 | error->dovsta = I915_READ(DOVSTA); |
| 1463 | error->isr = I915_READ(ISR); | 1461 | error->isr = I915_READ(ISR); |
| 1464 | if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) | 1462 | if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) |
| 1465 | error->base = (__force long)overlay->reg_bo->phys_obj->handle->vaddr; | 1463 | error->base = (__force long)overlay->reg_bo->phys_handle->vaddr; |
| 1466 | else | 1464 | else |
| 1467 | error->base = i915_gem_obj_ggtt_offset(overlay->reg_bo); | 1465 | error->base = i915_gem_obj_ggtt_offset(overlay->reg_bo); |
| 1468 | 1466 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 2b6e0ebcc13a..41ecf8a60611 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
| @@ -152,6 +152,12 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) | |||
| 152 | uint32_t domain = r->write_domain ? | 152 | uint32_t domain = r->write_domain ? |
| 153 | r->write_domain : r->read_domains; | 153 | r->write_domain : r->read_domains; |
| 154 | 154 | ||
| 155 | if (domain & RADEON_GEM_DOMAIN_CPU) { | ||
| 156 | DRM_ERROR("RADEON_GEM_DOMAIN_CPU is not valid " | ||
| 157 | "for command submission\n"); | ||
| 158 | return -EINVAL; | ||
| 159 | } | ||
| 160 | |||
| 155 | p->relocs[i].domain = domain; | 161 | p->relocs[i].domain = domain; |
| 156 | if (domain == RADEON_GEM_DOMAIN_VRAM) | 162 | if (domain == RADEON_GEM_DOMAIN_VRAM) |
| 157 | domain |= RADEON_GEM_DOMAIN_GTT; | 163 | domain |= RADEON_GEM_DOMAIN_GTT; |
| @@ -342,10 +348,17 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) | |||
| 342 | return -EINVAL; | 348 | return -EINVAL; |
| 343 | 349 | ||
| 344 | /* we only support VM on some SI+ rings */ | 350 | /* we only support VM on some SI+ rings */ |
| 345 | if ((p->rdev->asic->ring[p->ring]->cs_parse == NULL) && | 351 | if ((p->cs_flags & RADEON_CS_USE_VM) == 0) { |
| 346 | ((p->cs_flags & RADEON_CS_USE_VM) == 0)) { | 352 | if (p->rdev->asic->ring[p->ring]->cs_parse == NULL) { |
| 347 | DRM_ERROR("Ring %d requires VM!\n", p->ring); | 353 | DRM_ERROR("Ring %d requires VM!\n", p->ring); |
| 348 | return -EINVAL; | 354 | return -EINVAL; |
| 355 | } | ||
| 356 | } else { | ||
| 357 | if (p->rdev->asic->ring[p->ring]->ib_parse == NULL) { | ||
| 358 | DRM_ERROR("VM not supported on ring %d!\n", | ||
| 359 | p->ring); | ||
| 360 | return -EINVAL; | ||
| 361 | } | ||
| 349 | } | 362 | } |
| 350 | } | 363 | } |
| 351 | 364 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 0e770bbf7e29..14671406212f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -1533,11 +1533,6 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) | |||
| 1533 | 1533 | ||
| 1534 | radeon_restore_bios_scratch_regs(rdev); | 1534 | radeon_restore_bios_scratch_regs(rdev); |
| 1535 | 1535 | ||
| 1536 | if (fbcon) { | ||
| 1537 | radeon_fbdev_set_suspend(rdev, 0); | ||
| 1538 | console_unlock(); | ||
| 1539 | } | ||
| 1540 | |||
| 1541 | /* init dig PHYs, disp eng pll */ | 1536 | /* init dig PHYs, disp eng pll */ |
| 1542 | if (rdev->is_atom_bios) { | 1537 | if (rdev->is_atom_bios) { |
| 1543 | radeon_atom_encoder_init(rdev); | 1538 | radeon_atom_encoder_init(rdev); |
| @@ -1562,6 +1557,12 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) | |||
| 1562 | } | 1557 | } |
| 1563 | 1558 | ||
| 1564 | drm_kms_helper_poll_enable(dev); | 1559 | drm_kms_helper_poll_enable(dev); |
| 1560 | |||
| 1561 | if (fbcon) { | ||
| 1562 | radeon_fbdev_set_suspend(rdev, 0); | ||
| 1563 | console_unlock(); | ||
| 1564 | } | ||
| 1565 | |||
| 1565 | return 0; | 1566 | return 0; |
| 1566 | } | 1567 | } |
| 1567 | 1568 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index f00dbbf4d806..356b733caafe 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -862,7 +862,7 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, | |||
| 862 | unsigned *fb_div, unsigned *ref_div) | 862 | unsigned *fb_div, unsigned *ref_div) |
| 863 | { | 863 | { |
| 864 | /* limit reference * post divider to a maximum */ | 864 | /* limit reference * post divider to a maximum */ |
| 865 | ref_div_max = min(128 / post_div, ref_div_max); | 865 | ref_div_max = max(min(100 / post_div, ref_div_max), 1u); |
| 866 | 866 | ||
| 867 | /* get matching reference and feedback divider */ | 867 | /* get matching reference and feedback divider */ |
| 868 | *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max); | 868 | *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max); |
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index d9ab99f47612..1f426696de36 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c | |||
| @@ -130,10 +130,10 @@ struct radeon_cs_reloc *radeon_vm_get_bos(struct radeon_device *rdev, | |||
| 130 | struct list_head *head) | 130 | struct list_head *head) |
| 131 | { | 131 | { |
| 132 | struct radeon_cs_reloc *list; | 132 | struct radeon_cs_reloc *list; |
| 133 | unsigned i, idx, size; | 133 | unsigned i, idx; |
| 134 | 134 | ||
| 135 | size = (radeon_vm_num_pdes(rdev) + 1) * sizeof(struct radeon_cs_reloc); | 135 | list = kmalloc_array(vm->max_pde_used + 1, |
| 136 | list = kmalloc(size, GFP_KERNEL); | 136 | sizeof(struct radeon_cs_reloc), GFP_KERNEL); |
| 137 | if (!list) | 137 | if (!list) |
| 138 | return NULL; | 138 | return NULL; |
| 139 | 139 | ||
