diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 77 |
1 files changed, 47 insertions, 30 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ee896d91c5b..39f5c658ef5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -349,7 +349,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
349 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; | 349 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; |
350 | num_pages = last_data_page - first_data_page + 1; | 350 | num_pages = last_data_page - first_data_page + 1; |
351 | 351 | ||
352 | user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL); | 352 | user_pages = drm_calloc_large(num_pages, sizeof(struct page *)); |
353 | if (user_pages == NULL) | 353 | if (user_pages == NULL) |
354 | return -ENOMEM; | 354 | return -ENOMEM; |
355 | 355 | ||
@@ -429,7 +429,7 @@ fail_put_user_pages: | |||
429 | SetPageDirty(user_pages[i]); | 429 | SetPageDirty(user_pages[i]); |
430 | page_cache_release(user_pages[i]); | 430 | page_cache_release(user_pages[i]); |
431 | } | 431 | } |
432 | kfree(user_pages); | 432 | drm_free_large(user_pages); |
433 | 433 | ||
434 | return ret; | 434 | return ret; |
435 | } | 435 | } |
@@ -649,7 +649,7 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
649 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; | 649 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; |
650 | num_pages = last_data_page - first_data_page + 1; | 650 | num_pages = last_data_page - first_data_page + 1; |
651 | 651 | ||
652 | user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL); | 652 | user_pages = drm_calloc_large(num_pages, sizeof(struct page *)); |
653 | if (user_pages == NULL) | 653 | if (user_pages == NULL) |
654 | return -ENOMEM; | 654 | return -ENOMEM; |
655 | 655 | ||
@@ -719,7 +719,7 @@ out_unlock: | |||
719 | out_unpin_pages: | 719 | out_unpin_pages: |
720 | for (i = 0; i < pinned_pages; i++) | 720 | for (i = 0; i < pinned_pages; i++) |
721 | page_cache_release(user_pages[i]); | 721 | page_cache_release(user_pages[i]); |
722 | kfree(user_pages); | 722 | drm_free_large(user_pages); |
723 | 723 | ||
724 | return ret; | 724 | return ret; |
725 | } | 725 | } |
@@ -824,7 +824,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
824 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; | 824 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; |
825 | num_pages = last_data_page - first_data_page + 1; | 825 | num_pages = last_data_page - first_data_page + 1; |
826 | 826 | ||
827 | user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL); | 827 | user_pages = drm_calloc_large(num_pages, sizeof(struct page *)); |
828 | if (user_pages == NULL) | 828 | if (user_pages == NULL) |
829 | return -ENOMEM; | 829 | return -ENOMEM; |
830 | 830 | ||
@@ -902,7 +902,7 @@ fail_unlock: | |||
902 | fail_put_user_pages: | 902 | fail_put_user_pages: |
903 | for (i = 0; i < pinned_pages; i++) | 903 | for (i = 0; i < pinned_pages; i++) |
904 | page_cache_release(user_pages[i]); | 904 | page_cache_release(user_pages[i]); |
905 | kfree(user_pages); | 905 | drm_free_large(user_pages); |
906 | 906 | ||
907 | return ret; | 907 | return ret; |
908 | } | 908 | } |
@@ -1145,7 +1145,14 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1145 | mutex_unlock(&dev->struct_mutex); | 1145 | mutex_unlock(&dev->struct_mutex); |
1146 | return VM_FAULT_SIGBUS; | 1146 | return VM_FAULT_SIGBUS; |
1147 | } | 1147 | } |
1148 | list_add(&obj_priv->list, &dev_priv->mm.inactive_list); | 1148 | |
1149 | ret = i915_gem_object_set_to_gtt_domain(obj, write); | ||
1150 | if (ret) { | ||
1151 | mutex_unlock(&dev->struct_mutex); | ||
1152 | return VM_FAULT_SIGBUS; | ||
1153 | } | ||
1154 | |||
1155 | list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); | ||
1149 | } | 1156 | } |
1150 | 1157 | ||
1151 | /* Need a new fence register? */ | 1158 | /* Need a new fence register? */ |
@@ -1375,7 +1382,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
1375 | mutex_unlock(&dev->struct_mutex); | 1382 | mutex_unlock(&dev->struct_mutex); |
1376 | return ret; | 1383 | return ret; |
1377 | } | 1384 | } |
1378 | list_add(&obj_priv->list, &dev_priv->mm.inactive_list); | 1385 | list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); |
1379 | } | 1386 | } |
1380 | 1387 | ||
1381 | drm_gem_object_unreference(obj); | 1388 | drm_gem_object_unreference(obj); |
@@ -1408,9 +1415,7 @@ i915_gem_object_put_pages(struct drm_gem_object *obj) | |||
1408 | } | 1415 | } |
1409 | obj_priv->dirty = 0; | 1416 | obj_priv->dirty = 0; |
1410 | 1417 | ||
1411 | drm_free(obj_priv->pages, | 1418 | drm_free_large(obj_priv->pages); |
1412 | page_count * sizeof(struct page *), | ||
1413 | DRM_MEM_DRIVER); | ||
1414 | obj_priv->pages = NULL; | 1419 | obj_priv->pages = NULL; |
1415 | } | 1420 | } |
1416 | 1421 | ||
@@ -1691,11 +1696,20 @@ static int | |||
1691 | i915_wait_request(struct drm_device *dev, uint32_t seqno) | 1696 | i915_wait_request(struct drm_device *dev, uint32_t seqno) |
1692 | { | 1697 | { |
1693 | drm_i915_private_t *dev_priv = dev->dev_private; | 1698 | drm_i915_private_t *dev_priv = dev->dev_private; |
1699 | u32 ier; | ||
1694 | int ret = 0; | 1700 | int ret = 0; |
1695 | 1701 | ||
1696 | BUG_ON(seqno == 0); | 1702 | BUG_ON(seqno == 0); |
1697 | 1703 | ||
1698 | if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) { | 1704 | if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) { |
1705 | ier = I915_READ(IER); | ||
1706 | if (!ier) { | ||
1707 | DRM_ERROR("something (likely vbetool) disabled " | ||
1708 | "interrupts, re-enabling\n"); | ||
1709 | i915_driver_irq_preinstall(dev); | ||
1710 | i915_driver_irq_postinstall(dev); | ||
1711 | } | ||
1712 | |||
1699 | dev_priv->mm.waiting_gem_seqno = seqno; | 1713 | dev_priv->mm.waiting_gem_seqno = seqno; |
1700 | i915_user_irq_get(dev); | 1714 | i915_user_irq_get(dev); |
1701 | ret = wait_event_interruptible(dev_priv->irq_queue, | 1715 | ret = wait_event_interruptible(dev_priv->irq_queue, |
@@ -2015,8 +2029,7 @@ i915_gem_object_get_pages(struct drm_gem_object *obj) | |||
2015 | */ | 2029 | */ |
2016 | page_count = obj->size / PAGE_SIZE; | 2030 | page_count = obj->size / PAGE_SIZE; |
2017 | BUG_ON(obj_priv->pages != NULL); | 2031 | BUG_ON(obj_priv->pages != NULL); |
2018 | obj_priv->pages = drm_calloc(page_count, sizeof(struct page *), | 2032 | obj_priv->pages = drm_calloc_large(page_count, sizeof(struct page *)); |
2019 | DRM_MEM_DRIVER); | ||
2020 | if (obj_priv->pages == NULL) { | 2033 | if (obj_priv->pages == NULL) { |
2021 | DRM_ERROR("Faled to allocate page list\n"); | 2034 | DRM_ERROR("Faled to allocate page list\n"); |
2022 | obj_priv->pages_refcount--; | 2035 | obj_priv->pages_refcount--; |
@@ -2122,8 +2135,10 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
2122 | return; | 2135 | return; |
2123 | } | 2136 | } |
2124 | 2137 | ||
2125 | pitch_val = (obj_priv->stride / 128) - 1; | 2138 | pitch_val = obj_priv->stride / 128; |
2126 | WARN_ON(pitch_val & ~0x0000000f); | 2139 | pitch_val = ffs(pitch_val) - 1; |
2140 | WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL); | ||
2141 | |||
2127 | val = obj_priv->gtt_offset; | 2142 | val = obj_priv->gtt_offset; |
2128 | if (obj_priv->tiling_mode == I915_TILING_Y) | 2143 | if (obj_priv->tiling_mode == I915_TILING_Y) |
2129 | val |= 1 << I830_FENCE_TILING_Y_SHIFT; | 2144 | val |= 1 << I830_FENCE_TILING_Y_SHIFT; |
@@ -2245,9 +2260,6 @@ try_again: | |||
2245 | goto try_again; | 2260 | goto try_again; |
2246 | } | 2261 | } |
2247 | 2262 | ||
2248 | BUG_ON(old_obj_priv->active || | ||
2249 | (reg->obj->write_domain & I915_GEM_GPU_DOMAINS)); | ||
2250 | |||
2251 | /* | 2263 | /* |
2252 | * Zap this virtual mapping so we can set up a fence again | 2264 | * Zap this virtual mapping so we can set up a fence again |
2253 | * for this object next time we need it. | 2265 | * for this object next time we need it. |
@@ -2415,6 +2427,16 @@ i915_gem_clflush_object(struct drm_gem_object *obj) | |||
2415 | if (obj_priv->pages == NULL) | 2427 | if (obj_priv->pages == NULL) |
2416 | return; | 2428 | return; |
2417 | 2429 | ||
2430 | /* XXX: The 865 in particular appears to be weird in how it handles | ||
2431 | * cache flushing. We haven't figured it out, but the | ||
2432 | * clflush+agp_chipset_flush doesn't appear to successfully get the | ||
2433 | * data visible to the PGU, while wbinvd + agp_chipset_flush does. | ||
2434 | */ | ||
2435 | if (IS_I865G(obj->dev)) { | ||
2436 | wbinvd(); | ||
2437 | return; | ||
2438 | } | ||
2439 | |||
2418 | drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE); | 2440 | drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE); |
2419 | } | 2441 | } |
2420 | 2442 | ||
@@ -3102,7 +3124,7 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, | |||
3102 | reloc_count += exec_list[i].relocation_count; | 3124 | reloc_count += exec_list[i].relocation_count; |
3103 | } | 3125 | } |
3104 | 3126 | ||
3105 | *relocs = drm_calloc(reloc_count, sizeof(**relocs), DRM_MEM_DRIVER); | 3127 | *relocs = drm_calloc_large(reloc_count, sizeof(**relocs)); |
3106 | if (*relocs == NULL) | 3128 | if (*relocs == NULL) |
3107 | return -ENOMEM; | 3129 | return -ENOMEM; |
3108 | 3130 | ||
@@ -3116,8 +3138,7 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, | |||
3116 | exec_list[i].relocation_count * | 3138 | exec_list[i].relocation_count * |
3117 | sizeof(**relocs)); | 3139 | sizeof(**relocs)); |
3118 | if (ret != 0) { | 3140 | if (ret != 0) { |
3119 | drm_free(*relocs, reloc_count * sizeof(**relocs), | 3141 | drm_free_large(*relocs); |
3120 | DRM_MEM_DRIVER); | ||
3121 | *relocs = NULL; | 3142 | *relocs = NULL; |
3122 | return -EFAULT; | 3143 | return -EFAULT; |
3123 | } | 3144 | } |
@@ -3156,7 +3177,7 @@ i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list, | |||
3156 | } | 3177 | } |
3157 | 3178 | ||
3158 | err: | 3179 | err: |
3159 | drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER); | 3180 | drm_free_large(relocs); |
3160 | 3181 | ||
3161 | return ret; | 3182 | return ret; |
3162 | } | 3183 | } |
@@ -3189,10 +3210,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
3189 | return -EINVAL; | 3210 | return -EINVAL; |
3190 | } | 3211 | } |
3191 | /* Copy in the exec list from userland */ | 3212 | /* Copy in the exec list from userland */ |
3192 | exec_list = drm_calloc(sizeof(*exec_list), args->buffer_count, | 3213 | exec_list = drm_calloc_large(sizeof(*exec_list), args->buffer_count); |
3193 | DRM_MEM_DRIVER); | 3214 | object_list = drm_calloc_large(sizeof(*object_list), args->buffer_count); |
3194 | object_list = drm_calloc(sizeof(*object_list), args->buffer_count, | ||
3195 | DRM_MEM_DRIVER); | ||
3196 | if (exec_list == NULL || object_list == NULL) { | 3215 | if (exec_list == NULL || object_list == NULL) { |
3197 | DRM_ERROR("Failed to allocate exec or object list " | 3216 | DRM_ERROR("Failed to allocate exec or object list " |
3198 | "for %d buffers\n", | 3217 | "for %d buffers\n", |
@@ -3453,10 +3472,8 @@ err: | |||
3453 | } | 3472 | } |
3454 | 3473 | ||
3455 | pre_mutex_err: | 3474 | pre_mutex_err: |
3456 | drm_free(object_list, sizeof(*object_list) * args->buffer_count, | 3475 | drm_free_large(object_list); |
3457 | DRM_MEM_DRIVER); | 3476 | drm_free_large(exec_list); |
3458 | drm_free(exec_list, sizeof(*exec_list) * args->buffer_count, | ||
3459 | DRM_MEM_DRIVER); | ||
3460 | drm_free(cliprects, sizeof(*cliprects) * args->num_cliprects, | 3477 | drm_free(cliprects, sizeof(*cliprects) * args->num_cliprects, |
3461 | DRM_MEM_DRIVER); | 3478 | DRM_MEM_DRIVER); |
3462 | 3479 | ||