diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2010-11-11 03:41:57 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-11-21 22:25:22 -0500 |
commit | eba67093f535322cb4f1c4b737319c0907a0c81d (patch) | |
tree | 695b9a43d558a2870b23d6813f60387d7d61c614 /drivers/gpu/drm/ttm | |
parent | 65705962025df490d13df59ec57c5329d1bd0a16 (diff) |
drm/ttm: Fix up io_mem_reserve / io_mem_free calling
This patch attempts to fix up shortcomings with the current calling
sequences.
1) There's a fastpath where no locking occurs and only io_mem_reserved is
called to obtain needed info for mapping. The fastpath is set per
memory type manager.
2) If the fastpath is disabled, io_mem_reserve and io_mem_free will be exactly
balanced and not called recursively for the same struct ttm_mem_reg.
3) Optionally the driver can choose to enable a per memory type manager LRU
eviction mechanism that, when io_mem_reserve returns -EAGAIN will attempt
to kill user-space mappings of memory in that manager to free up needed
resources
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/ttm')
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo.c | 44 | ||||
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo_util.c | 129 | ||||
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo_vm.c | 23 |
3 files changed, 166 insertions, 30 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 25e4c2a1d1d..cf2ec562550 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
@@ -378,8 +378,13 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, | |||
378 | int ret = 0; | 378 | int ret = 0; |
379 | 379 | ||
380 | if (old_is_pci || new_is_pci || | 380 | if (old_is_pci || new_is_pci || |
381 | ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0)) | 381 | ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0)) { |
382 | ttm_bo_unmap_virtual(bo); | 382 | ret = ttm_mem_io_lock(old_man, true); |
383 | if (unlikely(ret != 0)) | ||
384 | goto out_err; | ||
385 | ttm_bo_unmap_virtual_locked(bo); | ||
386 | ttm_mem_io_unlock(old_man); | ||
387 | } | ||
383 | 388 | ||
384 | /* | 389 | /* |
385 | * Create and bind a ttm if required. | 390 | * Create and bind a ttm if required. |
@@ -466,7 +471,6 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) | |||
466 | ttm_tt_destroy(bo->ttm); | 471 | ttm_tt_destroy(bo->ttm); |
467 | bo->ttm = NULL; | 472 | bo->ttm = NULL; |
468 | } | 473 | } |
469 | |||
470 | ttm_bo_mem_put(bo, &bo->mem); | 474 | ttm_bo_mem_put(bo, &bo->mem); |
471 | 475 | ||
472 | atomic_set(&bo->reserved, 0); | 476 | atomic_set(&bo->reserved, 0); |
@@ -665,6 +669,7 @@ static void ttm_bo_release(struct kref *kref) | |||
665 | struct ttm_buffer_object *bo = | 669 | struct ttm_buffer_object *bo = |
666 | container_of(kref, struct ttm_buffer_object, kref); | 670 | container_of(kref, struct ttm_buffer_object, kref); |
667 | struct ttm_bo_device *bdev = bo->bdev; | 671 | struct ttm_bo_device *bdev = bo->bdev; |
672 | struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type]; | ||
668 | 673 | ||
669 | if (likely(bo->vm_node != NULL)) { | 674 | if (likely(bo->vm_node != NULL)) { |
670 | rb_erase(&bo->vm_rb, &bdev->addr_space_rb); | 675 | rb_erase(&bo->vm_rb, &bdev->addr_space_rb); |
@@ -672,6 +677,9 @@ static void ttm_bo_release(struct kref *kref) | |||
672 | bo->vm_node = NULL; | 677 | bo->vm_node = NULL; |
673 | } | 678 | } |
674 | write_unlock(&bdev->vm_lock); | 679 | write_unlock(&bdev->vm_lock); |
680 | ttm_mem_io_lock(man, false); | ||
681 | ttm_mem_io_free_vm(bo); | ||
682 | ttm_mem_io_unlock(man); | ||
675 | ttm_bo_cleanup_refs_or_queue(bo); | 683 | ttm_bo_cleanup_refs_or_queue(bo); |
676 | kref_put(&bo->list_kref, ttm_bo_release_list); | 684 | kref_put(&bo->list_kref, ttm_bo_release_list); |
677 | write_lock(&bdev->vm_lock); | 685 | write_lock(&bdev->vm_lock); |
@@ -728,7 +736,8 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, | |||
728 | 736 | ||
729 | evict_mem = bo->mem; | 737 | evict_mem = bo->mem; |
730 | evict_mem.mm_node = NULL; | 738 | evict_mem.mm_node = NULL; |
731 | evict_mem.bus.io_reserved = false; | 739 | evict_mem.bus.io_reserved_vm = false; |
740 | evict_mem.bus.io_reserved_count = 0; | ||
732 | 741 | ||
733 | placement.fpfn = 0; | 742 | placement.fpfn = 0; |
734 | placement.lpfn = 0; | 743 | placement.lpfn = 0; |
@@ -1065,7 +1074,8 @@ int ttm_bo_move_buffer(struct ttm_buffer_object *bo, | |||
1065 | mem.num_pages = bo->num_pages; | 1074 | mem.num_pages = bo->num_pages; |
1066 | mem.size = mem.num_pages << PAGE_SHIFT; | 1075 | mem.size = mem.num_pages << PAGE_SHIFT; |
1067 | mem.page_alignment = bo->mem.page_alignment; | 1076 | mem.page_alignment = bo->mem.page_alignment; |
1068 | mem.bus.io_reserved = false; | 1077 | mem.bus.io_reserved_vm = false; |
1078 | mem.bus.io_reserved_count = 0; | ||
1069 | /* | 1079 | /* |
1070 | * Determine where to move the buffer. | 1080 | * Determine where to move the buffer. |
1071 | */ | 1081 | */ |
@@ -1184,6 +1194,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev, | |||
1184 | INIT_LIST_HEAD(&bo->lru); | 1194 | INIT_LIST_HEAD(&bo->lru); |
1185 | INIT_LIST_HEAD(&bo->ddestroy); | 1195 | INIT_LIST_HEAD(&bo->ddestroy); |
1186 | INIT_LIST_HEAD(&bo->swap); | 1196 | INIT_LIST_HEAD(&bo->swap); |
1197 | INIT_LIST_HEAD(&bo->io_reserve_lru); | ||
1187 | bo->bdev = bdev; | 1198 | bo->bdev = bdev; |
1188 | bo->glob = bdev->glob; | 1199 | bo->glob = bdev->glob; |
1189 | bo->type = type; | 1200 | bo->type = type; |
@@ -1193,7 +1204,8 @@ int ttm_bo_init(struct ttm_bo_device *bdev, | |||
1193 | bo->mem.num_pages = bo->num_pages; | 1204 | bo->mem.num_pages = bo->num_pages; |
1194 | bo->mem.mm_node = NULL; | 1205 | bo->mem.mm_node = NULL; |
1195 | bo->mem.page_alignment = page_alignment; | 1206 | bo->mem.page_alignment = page_alignment; |
1196 | bo->mem.bus.io_reserved = false; | 1207 | bo->mem.bus.io_reserved_vm = false; |
1208 | bo->mem.bus.io_reserved_count = 0; | ||
1197 | bo->buffer_start = buffer_start & PAGE_MASK; | 1209 | bo->buffer_start = buffer_start & PAGE_MASK; |
1198 | bo->priv_flags = 0; | 1210 | bo->priv_flags = 0; |
1199 | bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED); | 1211 | bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED); |
@@ -1367,6 +1379,10 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, | |||
1367 | BUG_ON(type >= TTM_NUM_MEM_TYPES); | 1379 | BUG_ON(type >= TTM_NUM_MEM_TYPES); |
1368 | man = &bdev->man[type]; | 1380 | man = &bdev->man[type]; |
1369 | BUG_ON(man->has_type); | 1381 | BUG_ON(man->has_type); |
1382 | man->io_reserve_fastpath = true; | ||
1383 | man->use_io_reserve_lru = false; | ||
1384 | mutex_init(&man->io_reserve_mutex); | ||
1385 | INIT_LIST_HEAD(&man->io_reserve_lru); | ||
1370 | 1386 | ||
1371 | ret = bdev->driver->init_mem_type(bdev, type, man); | 1387 | ret = bdev->driver->init_mem_type(bdev, type, man); |
1372 | if (ret) | 1388 | if (ret) |
@@ -1574,7 +1590,7 @@ bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
1574 | return true; | 1590 | return true; |
1575 | } | 1591 | } |
1576 | 1592 | ||
1577 | void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) | 1593 | void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo) |
1578 | { | 1594 | { |
1579 | struct ttm_bo_device *bdev = bo->bdev; | 1595 | struct ttm_bo_device *bdev = bo->bdev; |
1580 | loff_t offset = (loff_t) bo->addr_space_offset; | 1596 | loff_t offset = (loff_t) bo->addr_space_offset; |
@@ -1583,8 +1599,20 @@ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) | |||
1583 | if (!bdev->dev_mapping) | 1599 | if (!bdev->dev_mapping) |
1584 | return; | 1600 | return; |
1585 | unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1); | 1601 | unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1); |
1586 | ttm_mem_io_free(bdev, &bo->mem); | 1602 | ttm_mem_io_free_vm(bo); |
1587 | } | 1603 | } |
1604 | |||
1605 | void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) | ||
1606 | { | ||
1607 | struct ttm_bo_device *bdev = bo->bdev; | ||
1608 | struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type]; | ||
1609 | |||
1610 | ttm_mem_io_lock(man, false); | ||
1611 | ttm_bo_unmap_virtual_locked(bo); | ||
1612 | ttm_mem_io_unlock(man); | ||
1613 | } | ||
1614 | |||
1615 | |||
1588 | EXPORT_SYMBOL(ttm_bo_unmap_virtual); | 1616 | EXPORT_SYMBOL(ttm_bo_unmap_virtual); |
1589 | 1617 | ||
1590 | static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo) | 1618 | static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo) |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 4b75133d660..a89839f83f6 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
@@ -75,37 +75,123 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, | |||
75 | } | 75 | } |
76 | EXPORT_SYMBOL(ttm_bo_move_ttm); | 76 | EXPORT_SYMBOL(ttm_bo_move_ttm); |
77 | 77 | ||
78 | int ttm_mem_io_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | 78 | int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible) |
79 | { | 79 | { |
80 | int ret; | 80 | if (likely(man->io_reserve_fastpath)) |
81 | return 0; | ||
82 | |||
83 | if (interruptible) | ||
84 | return mutex_lock_interruptible(&man->io_reserve_mutex); | ||
85 | |||
86 | mutex_lock(&man->io_reserve_mutex); | ||
87 | return 0; | ||
88 | } | ||
81 | 89 | ||
82 | if (!mem->bus.io_reserved) { | 90 | void ttm_mem_io_unlock(struct ttm_mem_type_manager *man) |
83 | mem->bus.io_reserved = true; | 91 | { |
92 | if (likely(man->io_reserve_fastpath)) | ||
93 | return; | ||
94 | |||
95 | mutex_unlock(&man->io_reserve_mutex); | ||
96 | } | ||
97 | |||
98 | static int ttm_mem_io_evict(struct ttm_mem_type_manager *man) | ||
99 | { | ||
100 | struct ttm_buffer_object *bo; | ||
101 | |||
102 | if (!man->use_io_reserve_lru || list_empty(&man->io_reserve_lru)) | ||
103 | return -EAGAIN; | ||
104 | |||
105 | bo = list_first_entry(&man->io_reserve_lru, | ||
106 | struct ttm_buffer_object, | ||
107 | io_reserve_lru); | ||
108 | list_del_init(&bo->io_reserve_lru); | ||
109 | ttm_bo_unmap_virtual_locked(bo); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int ttm_mem_io_reserve(struct ttm_bo_device *bdev, | ||
115 | struct ttm_mem_reg *mem) | ||
116 | { | ||
117 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; | ||
118 | int ret = 0; | ||
119 | |||
120 | if (!bdev->driver->io_mem_reserve) | ||
121 | return 0; | ||
122 | if (likely(man->io_reserve_fastpath)) | ||
123 | return bdev->driver->io_mem_reserve(bdev, mem); | ||
124 | |||
125 | if (bdev->driver->io_mem_reserve && | ||
126 | mem->bus.io_reserved_count++ == 0) { | ||
127 | retry: | ||
84 | ret = bdev->driver->io_mem_reserve(bdev, mem); | 128 | ret = bdev->driver->io_mem_reserve(bdev, mem); |
129 | if (ret == -EAGAIN) { | ||
130 | ret = ttm_mem_io_evict(man); | ||
131 | if (ret == 0) | ||
132 | goto retry; | ||
133 | } | ||
134 | } | ||
135 | return ret; | ||
136 | } | ||
137 | |||
138 | static void ttm_mem_io_free(struct ttm_bo_device *bdev, | ||
139 | struct ttm_mem_reg *mem) | ||
140 | { | ||
141 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; | ||
142 | |||
143 | if (likely(man->io_reserve_fastpath)) | ||
144 | return; | ||
145 | |||
146 | if (bdev->driver->io_mem_reserve && | ||
147 | --mem->bus.io_reserved_count == 0 && | ||
148 | bdev->driver->io_mem_free) | ||
149 | bdev->driver->io_mem_free(bdev, mem); | ||
150 | |||
151 | } | ||
152 | |||
153 | int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo) | ||
154 | { | ||
155 | struct ttm_mem_reg *mem = &bo->mem; | ||
156 | int ret; | ||
157 | |||
158 | if (!mem->bus.io_reserved_vm) { | ||
159 | struct ttm_mem_type_manager *man = | ||
160 | &bo->bdev->man[mem->mem_type]; | ||
161 | |||
162 | ret = ttm_mem_io_reserve(bo->bdev, mem); | ||
85 | if (unlikely(ret != 0)) | 163 | if (unlikely(ret != 0)) |
86 | return ret; | 164 | return ret; |
165 | mem->bus.io_reserved_vm = true; | ||
166 | if (man->use_io_reserve_lru) | ||
167 | list_add_tail(&bo->io_reserve_lru, | ||
168 | &man->io_reserve_lru); | ||
87 | } | 169 | } |
88 | return 0; | 170 | return 0; |
89 | } | 171 | } |
90 | 172 | ||
91 | void ttm_mem_io_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | 173 | void ttm_mem_io_free_vm(struct ttm_buffer_object *bo) |
92 | { | 174 | { |
93 | if (bdev->driver->io_mem_reserve) { | 175 | struct ttm_mem_reg *mem = &bo->mem; |
94 | if (mem->bus.io_reserved) { | 176 | |
95 | mem->bus.io_reserved = false; | 177 | if (mem->bus.io_reserved_vm) { |
96 | bdev->driver->io_mem_free(bdev, mem); | 178 | mem->bus.io_reserved_vm = false; |
97 | } | 179 | list_del_init(&bo->io_reserve_lru); |
180 | ttm_mem_io_free(bo->bdev, mem); | ||
98 | } | 181 | } |
99 | } | 182 | } |
100 | 183 | ||
101 | int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, | 184 | int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, |
102 | void **virtual) | 185 | void **virtual) |
103 | { | 186 | { |
187 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; | ||
104 | int ret; | 188 | int ret; |
105 | void *addr; | 189 | void *addr; |
106 | 190 | ||
107 | *virtual = NULL; | 191 | *virtual = NULL; |
192 | (void) ttm_mem_io_lock(man, false); | ||
108 | ret = ttm_mem_io_reserve(bdev, mem); | 193 | ret = ttm_mem_io_reserve(bdev, mem); |
194 | ttm_mem_io_unlock(man); | ||
109 | if (ret || !mem->bus.is_iomem) | 195 | if (ret || !mem->bus.is_iomem) |
110 | return ret; | 196 | return ret; |
111 | 197 | ||
@@ -117,7 +203,9 @@ int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, | |||
117 | else | 203 | else |
118 | addr = ioremap_nocache(mem->bus.base + mem->bus.offset, mem->bus.size); | 204 | addr = ioremap_nocache(mem->bus.base + mem->bus.offset, mem->bus.size); |
119 | if (!addr) { | 205 | if (!addr) { |
206 | (void) ttm_mem_io_lock(man, false); | ||
120 | ttm_mem_io_free(bdev, mem); | 207 | ttm_mem_io_free(bdev, mem); |
208 | ttm_mem_io_unlock(man); | ||
121 | return -ENOMEM; | 209 | return -ENOMEM; |
122 | } | 210 | } |
123 | } | 211 | } |
@@ -134,7 +222,9 @@ void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, | |||
134 | 222 | ||
135 | if (virtual && mem->bus.addr == NULL) | 223 | if (virtual && mem->bus.addr == NULL) |
136 | iounmap(virtual); | 224 | iounmap(virtual); |
225 | (void) ttm_mem_io_lock(man, false); | ||
137 | ttm_mem_io_free(bdev, mem); | 226 | ttm_mem_io_free(bdev, mem); |
227 | ttm_mem_io_unlock(man); | ||
138 | } | 228 | } |
139 | 229 | ||
140 | static int ttm_copy_io_page(void *dst, void *src, unsigned long page) | 230 | static int ttm_copy_io_page(void *dst, void *src, unsigned long page) |
@@ -231,7 +321,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, | |||
231 | struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type]; | 321 | struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type]; |
232 | struct ttm_tt *ttm = bo->ttm; | 322 | struct ttm_tt *ttm = bo->ttm; |
233 | struct ttm_mem_reg *old_mem = &bo->mem; | 323 | struct ttm_mem_reg *old_mem = &bo->mem; |
234 | struct ttm_mem_reg old_copy = *old_mem; | 324 | struct ttm_mem_reg old_copy; |
235 | void *old_iomap; | 325 | void *old_iomap; |
236 | void *new_iomap; | 326 | void *new_iomap; |
237 | int ret; | 327 | int ret; |
@@ -281,7 +371,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, | |||
281 | mb(); | 371 | mb(); |
282 | out2: | 372 | out2: |
283 | ttm_bo_free_old_node(bo); | 373 | ttm_bo_free_old_node(bo); |
284 | 374 | old_copy = *old_mem; | |
285 | *old_mem = *new_mem; | 375 | *old_mem = *new_mem; |
286 | new_mem->mm_node = NULL; | 376 | new_mem->mm_node = NULL; |
287 | 377 | ||
@@ -292,7 +382,7 @@ out2: | |||
292 | } | 382 | } |
293 | 383 | ||
294 | out1: | 384 | out1: |
295 | ttm_mem_reg_iounmap(bdev, new_mem, new_iomap); | 385 | ttm_mem_reg_iounmap(bdev, old_mem, new_iomap); |
296 | out: | 386 | out: |
297 | ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap); | 387 | ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap); |
298 | return ret; | 388 | return ret; |
@@ -341,6 +431,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, | |||
341 | INIT_LIST_HEAD(&fbo->ddestroy); | 431 | INIT_LIST_HEAD(&fbo->ddestroy); |
342 | INIT_LIST_HEAD(&fbo->lru); | 432 | INIT_LIST_HEAD(&fbo->lru); |
343 | INIT_LIST_HEAD(&fbo->swap); | 433 | INIT_LIST_HEAD(&fbo->swap); |
434 | INIT_LIST_HEAD(&fbo->io_reserve_lru); | ||
344 | fbo->vm_node = NULL; | 435 | fbo->vm_node = NULL; |
345 | atomic_set(&fbo->cpu_writers, 0); | 436 | atomic_set(&fbo->cpu_writers, 0); |
346 | 437 | ||
@@ -452,6 +543,8 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, | |||
452 | unsigned long start_page, unsigned long num_pages, | 543 | unsigned long start_page, unsigned long num_pages, |
453 | struct ttm_bo_kmap_obj *map) | 544 | struct ttm_bo_kmap_obj *map) |
454 | { | 545 | { |
546 | struct ttm_mem_type_manager *man = | ||
547 | &bo->bdev->man[bo->mem.mem_type]; | ||
455 | unsigned long offset, size; | 548 | unsigned long offset, size; |
456 | int ret; | 549 | int ret; |
457 | 550 | ||
@@ -466,7 +559,9 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, | |||
466 | if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC)) | 559 | if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC)) |
467 | return -EPERM; | 560 | return -EPERM; |
468 | #endif | 561 | #endif |
562 | (void) ttm_mem_io_lock(man, false); | ||
469 | ret = ttm_mem_io_reserve(bo->bdev, &bo->mem); | 563 | ret = ttm_mem_io_reserve(bo->bdev, &bo->mem); |
564 | ttm_mem_io_unlock(man); | ||
470 | if (ret) | 565 | if (ret) |
471 | return ret; | 566 | return ret; |
472 | if (!bo->mem.bus.is_iomem) { | 567 | if (!bo->mem.bus.is_iomem) { |
@@ -481,12 +576,15 @@ EXPORT_SYMBOL(ttm_bo_kmap); | |||
481 | 576 | ||
482 | void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) | 577 | void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) |
483 | { | 578 | { |
579 | struct ttm_buffer_object *bo = map->bo; | ||
580 | struct ttm_mem_type_manager *man = | ||
581 | &bo->bdev->man[bo->mem.mem_type]; | ||
582 | |||
484 | if (!map->virtual) | 583 | if (!map->virtual) |
485 | return; | 584 | return; |
486 | switch (map->bo_kmap_type) { | 585 | switch (map->bo_kmap_type) { |
487 | case ttm_bo_map_iomap: | 586 | case ttm_bo_map_iomap: |
488 | iounmap(map->virtual); | 587 | iounmap(map->virtual); |
489 | ttm_mem_io_free(map->bo->bdev, &map->bo->mem); | ||
490 | break; | 588 | break; |
491 | case ttm_bo_map_vmap: | 589 | case ttm_bo_map_vmap: |
492 | vunmap(map->virtual); | 590 | vunmap(map->virtual); |
@@ -499,6 +597,9 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) | |||
499 | default: | 597 | default: |
500 | BUG(); | 598 | BUG(); |
501 | } | 599 | } |
600 | (void) ttm_mem_io_lock(man, false); | ||
601 | ttm_mem_io_free(map->bo->bdev, &map->bo->mem); | ||
602 | ttm_mem_io_unlock(man); | ||
502 | map->virtual = NULL; | 603 | map->virtual = NULL; |
503 | map->page = NULL; | 604 | map->page = NULL; |
504 | } | 605 | } |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 8dd446cb778..221b924aceb 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c | |||
@@ -83,6 +83,8 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
83 | int i; | 83 | int i; |
84 | unsigned long address = (unsigned long)vmf->virtual_address; | 84 | unsigned long address = (unsigned long)vmf->virtual_address; |
85 | int retval = VM_FAULT_NOPAGE; | 85 | int retval = VM_FAULT_NOPAGE; |
86 | struct ttm_mem_type_manager *man = | ||
87 | &bdev->man[bo->mem.mem_type]; | ||
86 | 88 | ||
87 | /* | 89 | /* |
88 | * Work around locking order reversal in fault / nopfn | 90 | * Work around locking order reversal in fault / nopfn |
@@ -130,12 +132,16 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
130 | } else | 132 | } else |
131 | spin_unlock(&bdev->fence_lock); | 133 | spin_unlock(&bdev->fence_lock); |
132 | 134 | ||
133 | 135 | ret = ttm_mem_io_lock(man, true); | |
134 | ret = ttm_mem_io_reserve(bdev, &bo->mem); | 136 | if (unlikely(ret != 0)) { |
135 | if (ret) { | 137 | retval = VM_FAULT_NOPAGE; |
136 | retval = VM_FAULT_SIGBUS; | ||
137 | goto out_unlock; | 138 | goto out_unlock; |
138 | } | 139 | } |
140 | ret = ttm_mem_io_reserve_vm(bo); | ||
141 | if (unlikely(ret != 0)) { | ||
142 | retval = VM_FAULT_SIGBUS; | ||
143 | goto out_io_unlock; | ||
144 | } | ||
139 | 145 | ||
140 | page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + | 146 | page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + |
141 | bo->vm_node->start - vma->vm_pgoff; | 147 | bo->vm_node->start - vma->vm_pgoff; |
@@ -144,7 +150,7 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
144 | 150 | ||
145 | if (unlikely(page_offset >= bo->num_pages)) { | 151 | if (unlikely(page_offset >= bo->num_pages)) { |
146 | retval = VM_FAULT_SIGBUS; | 152 | retval = VM_FAULT_SIGBUS; |
147 | goto out_unlock; | 153 | goto out_io_unlock; |
148 | } | 154 | } |
149 | 155 | ||
150 | /* | 156 | /* |
@@ -182,7 +188,7 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
182 | page = ttm_tt_get_page(ttm, page_offset); | 188 | page = ttm_tt_get_page(ttm, page_offset); |
183 | if (unlikely(!page && i == 0)) { | 189 | if (unlikely(!page && i == 0)) { |
184 | retval = VM_FAULT_OOM; | 190 | retval = VM_FAULT_OOM; |
185 | goto out_unlock; | 191 | goto out_io_unlock; |
186 | } else if (unlikely(!page)) { | 192 | } else if (unlikely(!page)) { |
187 | break; | 193 | break; |
188 | } | 194 | } |
@@ -200,14 +206,15 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
200 | else if (unlikely(ret != 0)) { | 206 | else if (unlikely(ret != 0)) { |
201 | retval = | 207 | retval = |
202 | (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; | 208 | (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; |
203 | goto out_unlock; | 209 | goto out_io_unlock; |
204 | } | 210 | } |
205 | 211 | ||
206 | address += PAGE_SIZE; | 212 | address += PAGE_SIZE; |
207 | if (unlikely(++page_offset >= page_last)) | 213 | if (unlikely(++page_offset >= page_last)) |
208 | break; | 214 | break; |
209 | } | 215 | } |
210 | 216 | out_io_unlock: | |
217 | ttm_mem_io_unlock(man); | ||
211 | out_unlock: | 218 | out_unlock: |
212 | ttm_bo_unreserve(bo); | 219 | ttm_bo_unreserve(bo); |
213 | return retval; | 220 | return retval; |