diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 185 |
1 files changed, 118 insertions, 67 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 818576654092..28b726d07a0c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -34,10 +34,6 @@ | |||
34 | 34 | ||
35 | #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) | 35 | #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) |
36 | 36 | ||
37 | static void | ||
38 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | ||
39 | uint32_t read_domains, | ||
40 | uint32_t write_domain); | ||
41 | static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); | 37 | static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); |
42 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); | 38 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); |
43 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); | 39 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); |
@@ -607,8 +603,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
607 | case -EAGAIN: | 603 | case -EAGAIN: |
608 | return VM_FAULT_OOM; | 604 | return VM_FAULT_OOM; |
609 | case -EFAULT: | 605 | case -EFAULT: |
610 | case -EBUSY: | ||
611 | DRM_ERROR("can't insert pfn?? fault or busy...\n"); | ||
612 | return VM_FAULT_SIGBUS; | 606 | return VM_FAULT_SIGBUS; |
613 | default: | 607 | default: |
614 | return VM_FAULT_NOPAGE; | 608 | return VM_FAULT_NOPAGE; |
@@ -684,6 +678,30 @@ out_free_list: | |||
684 | return ret; | 678 | return ret; |
685 | } | 679 | } |
686 | 680 | ||
681 | static void | ||
682 | i915_gem_free_mmap_offset(struct drm_gem_object *obj) | ||
683 | { | ||
684 | struct drm_device *dev = obj->dev; | ||
685 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
686 | struct drm_gem_mm *mm = dev->mm_private; | ||
687 | struct drm_map_list *list; | ||
688 | |||
689 | list = &obj->map_list; | ||
690 | drm_ht_remove_item(&mm->offset_hash, &list->hash); | ||
691 | |||
692 | if (list->file_offset_node) { | ||
693 | drm_mm_put_block(list->file_offset_node); | ||
694 | list->file_offset_node = NULL; | ||
695 | } | ||
696 | |||
697 | if (list->map) { | ||
698 | drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER); | ||
699 | list->map = NULL; | ||
700 | } | ||
701 | |||
702 | obj_priv->mmap_offset = 0; | ||
703 | } | ||
704 | |||
687 | /** | 705 | /** |
688 | * i915_gem_get_gtt_alignment - return required GTT alignment for an object | 706 | * i915_gem_get_gtt_alignment - return required GTT alignment for an object |
689 | * @obj: object to check | 707 | * @obj: object to check |
@@ -758,8 +776,11 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
758 | 776 | ||
759 | if (!obj_priv->mmap_offset) { | 777 | if (!obj_priv->mmap_offset) { |
760 | ret = i915_gem_create_mmap_offset(obj); | 778 | ret = i915_gem_create_mmap_offset(obj); |
761 | if (ret) | 779 | if (ret) { |
780 | drm_gem_object_unreference(obj); | ||
781 | mutex_unlock(&dev->struct_mutex); | ||
762 | return ret; | 782 | return ret; |
783 | } | ||
763 | } | 784 | } |
764 | 785 | ||
765 | args->offset = obj_priv->mmap_offset; | 786 | args->offset = obj_priv->mmap_offset; |
@@ -1030,6 +1051,9 @@ i915_gem_retire_requests(struct drm_device *dev) | |||
1030 | drm_i915_private_t *dev_priv = dev->dev_private; | 1051 | drm_i915_private_t *dev_priv = dev->dev_private; |
1031 | uint32_t seqno; | 1052 | uint32_t seqno; |
1032 | 1053 | ||
1054 | if (!dev_priv->hw_status_page) | ||
1055 | return; | ||
1056 | |||
1033 | seqno = i915_get_gem_seqno(dev); | 1057 | seqno = i915_get_gem_seqno(dev); |
1034 | 1058 | ||
1035 | while (!list_empty(&dev_priv->mm.request_list)) { | 1059 | while (!list_empty(&dev_priv->mm.request_list)) { |
@@ -1996,30 +2020,28 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
1996 | * drm_agp_chipset_flush | 2020 | * drm_agp_chipset_flush |
1997 | */ | 2021 | */ |
1998 | static void | 2022 | static void |
1999 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | 2023 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) |
2000 | uint32_t read_domains, | ||
2001 | uint32_t write_domain) | ||
2002 | { | 2024 | { |
2003 | struct drm_device *dev = obj->dev; | 2025 | struct drm_device *dev = obj->dev; |
2004 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 2026 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
2005 | uint32_t invalidate_domains = 0; | 2027 | uint32_t invalidate_domains = 0; |
2006 | uint32_t flush_domains = 0; | 2028 | uint32_t flush_domains = 0; |
2007 | 2029 | ||
2008 | BUG_ON(read_domains & I915_GEM_DOMAIN_CPU); | 2030 | BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU); |
2009 | BUG_ON(write_domain == I915_GEM_DOMAIN_CPU); | 2031 | BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU); |
2010 | 2032 | ||
2011 | #if WATCH_BUF | 2033 | #if WATCH_BUF |
2012 | DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n", | 2034 | DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n", |
2013 | __func__, obj, | 2035 | __func__, obj, |
2014 | obj->read_domains, read_domains, | 2036 | obj->read_domains, obj->pending_read_domains, |
2015 | obj->write_domain, write_domain); | 2037 | obj->write_domain, obj->pending_write_domain); |
2016 | #endif | 2038 | #endif |
2017 | /* | 2039 | /* |
2018 | * If the object isn't moving to a new write domain, | 2040 | * If the object isn't moving to a new write domain, |
2019 | * let the object stay in multiple read domains | 2041 | * let the object stay in multiple read domains |
2020 | */ | 2042 | */ |
2021 | if (write_domain == 0) | 2043 | if (obj->pending_write_domain == 0) |
2022 | read_domains |= obj->read_domains; | 2044 | obj->pending_read_domains |= obj->read_domains; |
2023 | else | 2045 | else |
2024 | obj_priv->dirty = 1; | 2046 | obj_priv->dirty = 1; |
2025 | 2047 | ||
@@ -2029,15 +2051,17 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | |||
2029 | * any read domains which differ from the old | 2051 | * any read domains which differ from the old |
2030 | * write domain | 2052 | * write domain |
2031 | */ | 2053 | */ |
2032 | if (obj->write_domain && obj->write_domain != read_domains) { | 2054 | if (obj->write_domain && |
2055 | obj->write_domain != obj->pending_read_domains) { | ||
2033 | flush_domains |= obj->write_domain; | 2056 | flush_domains |= obj->write_domain; |
2034 | invalidate_domains |= read_domains & ~obj->write_domain; | 2057 | invalidate_domains |= |
2058 | obj->pending_read_domains & ~obj->write_domain; | ||
2035 | } | 2059 | } |
2036 | /* | 2060 | /* |
2037 | * Invalidate any read caches which may have | 2061 | * Invalidate any read caches which may have |
2038 | * stale data. That is, any new read domains. | 2062 | * stale data. That is, any new read domains. |
2039 | */ | 2063 | */ |
2040 | invalidate_domains |= read_domains & ~obj->read_domains; | 2064 | invalidate_domains |= obj->pending_read_domains & ~obj->read_domains; |
2041 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) { | 2065 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) { |
2042 | #if WATCH_BUF | 2066 | #if WATCH_BUF |
2043 | DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n", | 2067 | DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n", |
@@ -2046,9 +2070,15 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | |||
2046 | i915_gem_clflush_object(obj); | 2070 | i915_gem_clflush_object(obj); |
2047 | } | 2071 | } |
2048 | 2072 | ||
2049 | if ((write_domain | flush_domains) != 0) | 2073 | /* The actual obj->write_domain will be updated with |
2050 | obj->write_domain = write_domain; | 2074 | * pending_write_domain after we emit the accumulated flush for all |
2051 | obj->read_domains = read_domains; | 2075 | * of our domain changes in execbuffers (which clears objects' |
2076 | * write_domains). So if we have a current write domain that we | ||
2077 | * aren't changing, set pending_write_domain to that. | ||
2078 | */ | ||
2079 | if (flush_domains == 0 && obj->pending_write_domain == 0) | ||
2080 | obj->pending_write_domain = obj->write_domain; | ||
2081 | obj->read_domains = obj->pending_read_domains; | ||
2052 | 2082 | ||
2053 | dev->invalidate_domains |= invalidate_domains; | 2083 | dev->invalidate_domains |= invalidate_domains; |
2054 | dev->flush_domains |= flush_domains; | 2084 | dev->flush_domains |= flush_domains; |
@@ -2251,6 +2281,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
2251 | (int) reloc.offset, | 2281 | (int) reloc.offset, |
2252 | reloc.read_domains, | 2282 | reloc.read_domains, |
2253 | reloc.write_domain); | 2283 | reloc.write_domain); |
2284 | drm_gem_object_unreference(target_obj); | ||
2285 | i915_gem_object_unpin(obj); | ||
2254 | return -EINVAL; | 2286 | return -EINVAL; |
2255 | } | 2287 | } |
2256 | 2288 | ||
@@ -2480,13 +2512,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2480 | if (dev_priv->mm.wedged) { | 2512 | if (dev_priv->mm.wedged) { |
2481 | DRM_ERROR("Execbuf while wedged\n"); | 2513 | DRM_ERROR("Execbuf while wedged\n"); |
2482 | mutex_unlock(&dev->struct_mutex); | 2514 | mutex_unlock(&dev->struct_mutex); |
2483 | return -EIO; | 2515 | ret = -EIO; |
2516 | goto pre_mutex_err; | ||
2484 | } | 2517 | } |
2485 | 2518 | ||
2486 | if (dev_priv->mm.suspended) { | 2519 | if (dev_priv->mm.suspended) { |
2487 | DRM_ERROR("Execbuf while VT-switched.\n"); | 2520 | DRM_ERROR("Execbuf while VT-switched.\n"); |
2488 | mutex_unlock(&dev->struct_mutex); | 2521 | mutex_unlock(&dev->struct_mutex); |
2489 | return -EBUSY; | 2522 | ret = -EBUSY; |
2523 | goto pre_mutex_err; | ||
2490 | } | 2524 | } |
2491 | 2525 | ||
2492 | /* Look up object handles */ | 2526 | /* Look up object handles */ |
@@ -2554,9 +2588,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2554 | struct drm_gem_object *obj = object_list[i]; | 2588 | struct drm_gem_object *obj = object_list[i]; |
2555 | 2589 | ||
2556 | /* Compute new gpu domains and update invalidate/flush */ | 2590 | /* Compute new gpu domains and update invalidate/flush */ |
2557 | i915_gem_object_set_to_gpu_domain(obj, | 2591 | i915_gem_object_set_to_gpu_domain(obj); |
2558 | obj->pending_read_domains, | ||
2559 | obj->pending_write_domain); | ||
2560 | } | 2592 | } |
2561 | 2593 | ||
2562 | i915_verify_inactive(dev, __FILE__, __LINE__); | 2594 | i915_verify_inactive(dev, __FILE__, __LINE__); |
@@ -2575,6 +2607,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2575 | (void)i915_add_request(dev, dev->flush_domains); | 2607 | (void)i915_add_request(dev, dev->flush_domains); |
2576 | } | 2608 | } |
2577 | 2609 | ||
2610 | for (i = 0; i < args->buffer_count; i++) { | ||
2611 | struct drm_gem_object *obj = object_list[i]; | ||
2612 | |||
2613 | obj->write_domain = obj->pending_write_domain; | ||
2614 | } | ||
2615 | |||
2578 | i915_verify_inactive(dev, __FILE__, __LINE__); | 2616 | i915_verify_inactive(dev, __FILE__, __LINE__); |
2579 | 2617 | ||
2580 | #if WATCH_COHERENCY | 2618 | #if WATCH_COHERENCY |
@@ -2632,15 +2670,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2632 | 2670 | ||
2633 | i915_verify_inactive(dev, __FILE__, __LINE__); | 2671 | i915_verify_inactive(dev, __FILE__, __LINE__); |
2634 | 2672 | ||
2635 | /* Copy the new buffer offsets back to the user's exec list. */ | ||
2636 | ret = copy_to_user((struct drm_i915_relocation_entry __user *) | ||
2637 | (uintptr_t) args->buffers_ptr, | ||
2638 | exec_list, | ||
2639 | sizeof(*exec_list) * args->buffer_count); | ||
2640 | if (ret) | ||
2641 | DRM_ERROR("failed to copy %d exec entries " | ||
2642 | "back to user (%d)\n", | ||
2643 | args->buffer_count, ret); | ||
2644 | err: | 2673 | err: |
2645 | for (i = 0; i < pinned; i++) | 2674 | for (i = 0; i < pinned; i++) |
2646 | i915_gem_object_unpin(object_list[i]); | 2675 | i915_gem_object_unpin(object_list[i]); |
@@ -2650,6 +2679,18 @@ err: | |||
2650 | 2679 | ||
2651 | mutex_unlock(&dev->struct_mutex); | 2680 | mutex_unlock(&dev->struct_mutex); |
2652 | 2681 | ||
2682 | if (!ret) { | ||
2683 | /* Copy the new buffer offsets back to the user's exec list. */ | ||
2684 | ret = copy_to_user((struct drm_i915_relocation_entry __user *) | ||
2685 | (uintptr_t) args->buffers_ptr, | ||
2686 | exec_list, | ||
2687 | sizeof(*exec_list) * args->buffer_count); | ||
2688 | if (ret) | ||
2689 | DRM_ERROR("failed to copy %d exec entries " | ||
2690 | "back to user (%d)\n", | ||
2691 | args->buffer_count, ret); | ||
2692 | } | ||
2693 | |||
2653 | pre_mutex_err: | 2694 | pre_mutex_err: |
2654 | drm_free(object_list, sizeof(*object_list) * args->buffer_count, | 2695 | drm_free(object_list, sizeof(*object_list) * args->buffer_count, |
2655 | DRM_MEM_DRIVER); | 2696 | DRM_MEM_DRIVER); |
@@ -2753,6 +2794,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
2753 | if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { | 2794 | if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { |
2754 | DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", | 2795 | DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", |
2755 | args->handle); | 2796 | args->handle); |
2797 | drm_gem_object_unreference(obj); | ||
2756 | mutex_unlock(&dev->struct_mutex); | 2798 | mutex_unlock(&dev->struct_mutex); |
2757 | return -EINVAL; | 2799 | return -EINVAL; |
2758 | } | 2800 | } |
@@ -2833,6 +2875,13 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
2833 | return -EBADF; | 2875 | return -EBADF; |
2834 | } | 2876 | } |
2835 | 2877 | ||
2878 | /* Update the active list for the hardware's current position. | ||
2879 | * Otherwise this only updates on a delayed timer or when irqs are | ||
2880 | * actually unmasked, and our working set ends up being larger than | ||
2881 | * required. | ||
2882 | */ | ||
2883 | i915_gem_retire_requests(dev); | ||
2884 | |||
2836 | obj_priv = obj->driver_private; | 2885 | obj_priv = obj->driver_private; |
2837 | /* Don't count being on the flushing list against the object being | 2886 | /* Don't count being on the flushing list against the object being |
2838 | * done. Otherwise, a buffer left on the flushing list but not getting | 2887 | * done. Otherwise, a buffer left on the flushing list but not getting |
@@ -2885,9 +2934,6 @@ int i915_gem_init_object(struct drm_gem_object *obj) | |||
2885 | void i915_gem_free_object(struct drm_gem_object *obj) | 2934 | void i915_gem_free_object(struct drm_gem_object *obj) |
2886 | { | 2935 | { |
2887 | struct drm_device *dev = obj->dev; | 2936 | struct drm_device *dev = obj->dev; |
2888 | struct drm_gem_mm *mm = dev->mm_private; | ||
2889 | struct drm_map_list *list; | ||
2890 | struct drm_map *map; | ||
2891 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 2937 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
2892 | 2938 | ||
2893 | while (obj_priv->pin_count > 0) | 2939 | while (obj_priv->pin_count > 0) |
@@ -2898,19 +2944,7 @@ void i915_gem_free_object(struct drm_gem_object *obj) | |||
2898 | 2944 | ||
2899 | i915_gem_object_unbind(obj); | 2945 | i915_gem_object_unbind(obj); |
2900 | 2946 | ||
2901 | list = &obj->map_list; | 2947 | i915_gem_free_mmap_offset(obj); |
2902 | drm_ht_remove_item(&mm->offset_hash, &list->hash); | ||
2903 | |||
2904 | if (list->file_offset_node) { | ||
2905 | drm_mm_put_block(list->file_offset_node); | ||
2906 | list->file_offset_node = NULL; | ||
2907 | } | ||
2908 | |||
2909 | map = list->map; | ||
2910 | if (map) { | ||
2911 | drm_free(map, sizeof(*map), DRM_MEM_DRIVER); | ||
2912 | list->map = NULL; | ||
2913 | } | ||
2914 | 2948 | ||
2915 | drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); | 2949 | drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); |
2916 | drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); | 2950 | drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); |
@@ -2949,7 +2983,7 @@ i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head) | |||
2949 | return 0; | 2983 | return 0; |
2950 | } | 2984 | } |
2951 | 2985 | ||
2952 | static int | 2986 | int |
2953 | i915_gem_idle(struct drm_device *dev) | 2987 | i915_gem_idle(struct drm_device *dev) |
2954 | { | 2988 | { |
2955 | drm_i915_private_t *dev_priv = dev->dev_private; | 2989 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -3095,6 +3129,7 @@ i915_gem_init_hws(struct drm_device *dev) | |||
3095 | if (dev_priv->hw_status_page == NULL) { | 3129 | if (dev_priv->hw_status_page == NULL) { |
3096 | DRM_ERROR("Failed to map status page.\n"); | 3130 | DRM_ERROR("Failed to map status page.\n"); |
3097 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); | 3131 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); |
3132 | i915_gem_object_unpin(obj); | ||
3098 | drm_gem_object_unreference(obj); | 3133 | drm_gem_object_unreference(obj); |
3099 | return -EINVAL; | 3134 | return -EINVAL; |
3100 | } | 3135 | } |
@@ -3107,6 +3142,31 @@ i915_gem_init_hws(struct drm_device *dev) | |||
3107 | return 0; | 3142 | return 0; |
3108 | } | 3143 | } |
3109 | 3144 | ||
3145 | static void | ||
3146 | i915_gem_cleanup_hws(struct drm_device *dev) | ||
3147 | { | ||
3148 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
3149 | struct drm_gem_object *obj; | ||
3150 | struct drm_i915_gem_object *obj_priv; | ||
3151 | |||
3152 | if (dev_priv->hws_obj == NULL) | ||
3153 | return; | ||
3154 | |||
3155 | obj = dev_priv->hws_obj; | ||
3156 | obj_priv = obj->driver_private; | ||
3157 | |||
3158 | kunmap(obj_priv->page_list[0]); | ||
3159 | i915_gem_object_unpin(obj); | ||
3160 | drm_gem_object_unreference(obj); | ||
3161 | dev_priv->hws_obj = NULL; | ||
3162 | |||
3163 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); | ||
3164 | dev_priv->hw_status_page = NULL; | ||
3165 | |||
3166 | /* Write high address into HWS_PGA when disabling. */ | ||
3167 | I915_WRITE(HWS_PGA, 0x1ffff000); | ||
3168 | } | ||
3169 | |||
3110 | int | 3170 | int |
3111 | i915_gem_init_ringbuffer(struct drm_device *dev) | 3171 | i915_gem_init_ringbuffer(struct drm_device *dev) |
3112 | { | 3172 | { |
@@ -3124,6 +3184,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
3124 | obj = drm_gem_object_alloc(dev, 128 * 1024); | 3184 | obj = drm_gem_object_alloc(dev, 128 * 1024); |
3125 | if (obj == NULL) { | 3185 | if (obj == NULL) { |
3126 | DRM_ERROR("Failed to allocate ringbuffer\n"); | 3186 | DRM_ERROR("Failed to allocate ringbuffer\n"); |
3187 | i915_gem_cleanup_hws(dev); | ||
3127 | return -ENOMEM; | 3188 | return -ENOMEM; |
3128 | } | 3189 | } |
3129 | obj_priv = obj->driver_private; | 3190 | obj_priv = obj->driver_private; |
@@ -3131,6 +3192,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
3131 | ret = i915_gem_object_pin(obj, 4096); | 3192 | ret = i915_gem_object_pin(obj, 4096); |
3132 | if (ret != 0) { | 3193 | if (ret != 0) { |
3133 | drm_gem_object_unreference(obj); | 3194 | drm_gem_object_unreference(obj); |
3195 | i915_gem_cleanup_hws(dev); | ||
3134 | return ret; | 3196 | return ret; |
3135 | } | 3197 | } |
3136 | 3198 | ||
@@ -3148,7 +3210,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
3148 | if (ring->map.handle == NULL) { | 3210 | if (ring->map.handle == NULL) { |
3149 | DRM_ERROR("Failed to map ringbuffer.\n"); | 3211 | DRM_ERROR("Failed to map ringbuffer.\n"); |
3150 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); | 3212 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); |
3213 | i915_gem_object_unpin(obj); | ||
3151 | drm_gem_object_unreference(obj); | 3214 | drm_gem_object_unreference(obj); |
3215 | i915_gem_cleanup_hws(dev); | ||
3152 | return -EINVAL; | 3216 | return -EINVAL; |
3153 | } | 3217 | } |
3154 | ring->ring_obj = obj; | 3218 | ring->ring_obj = obj; |
@@ -3228,20 +3292,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) | |||
3228 | dev_priv->ring.ring_obj = NULL; | 3292 | dev_priv->ring.ring_obj = NULL; |
3229 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); | 3293 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); |
3230 | 3294 | ||
3231 | if (dev_priv->hws_obj != NULL) { | 3295 | i915_gem_cleanup_hws(dev); |
3232 | struct drm_gem_object *obj = dev_priv->hws_obj; | ||
3233 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
3234 | |||
3235 | kunmap(obj_priv->page_list[0]); | ||
3236 | i915_gem_object_unpin(obj); | ||
3237 | drm_gem_object_unreference(obj); | ||
3238 | dev_priv->hws_obj = NULL; | ||
3239 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); | ||
3240 | dev_priv->hw_status_page = NULL; | ||
3241 | |||
3242 | /* Write high address into HWS_PGA when disabling. */ | ||
3243 | I915_WRITE(HWS_PGA, 0x1ffff000); | ||
3244 | } | ||
3245 | } | 3296 | } |
3246 | 3297 | ||
3247 | int | 3298 | int |