Rev 5078 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5078 | Rev 6296 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /************************************************************************** |
1 | /************************************************************************** |
2 | * |
2 | * |
3 | * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA |
3 | * Copyright © 2011-2015 VMware, Inc., Palo Alto, CA., USA |
4 | * All Rights Reserved. |
4 | * All Rights Reserved. |
5 | * |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the |
7 | * copy of this software and associated documentation files (the |
8 | * "Software"), to deal in the Software without restriction, including |
8 | * "Software"), to deal in the Software without restriction, including |
Line 30... | Line 30... | ||
30 | #include |
30 | #include |
31 | #include "vmwgfx_drv.h" |
31 | #include "vmwgfx_drv.h" |
Line 32... | Line 32... | ||
32 | 32 | ||
33 | 33 | ||
34 | /** |
34 | /** |
35 | * vmw_dmabuf_to_placement - Validate a buffer to placement. |
35 | * vmw_dmabuf_pin_in_placement - Validate a buffer to placement. |
36 | * |
36 | * |
37 | * @dev_priv: Driver private. |
37 | * @dev_priv: Driver private. |
38 | * @buf: DMA buffer to move. |
38 | * @buf: DMA buffer to move. |
39 | * @pin: Pin buffer if true. |
39 | * @placement: The placement to pin it. |
40 | * @interruptible: Use interruptible wait. |
- | |
41 | * |
- | |
42 | * May only be called by the current master since it assumes that the |
- | |
43 | * master lock is the current master's lock. |
- | |
44 | * This function takes the master's lock in write mode. |
- | |
45 | * Flushes and unpins the query bo to avoid failures. |
40 | * @interruptible: Use interruptible wait. |
46 | * |
41 | * |
47 | * Returns |
42 | * Returns |
48 | * -ERESTARTSYS if interrupted by a signal. |
43 | * -ERESTARTSYS if interrupted by a signal. |
49 | */ |
44 | */ |
50 | int vmw_dmabuf_to_placement(struct vmw_private *dev_priv, |
45 | int vmw_dmabuf_pin_in_placement(struct vmw_private *dev_priv, |
51 | struct vmw_dma_buffer *buf, |
46 | struct vmw_dma_buffer *buf, |
52 | struct ttm_placement *placement, |
47 | struct ttm_placement *placement, |
53 | bool interruptible) |
48 | bool interruptible) |
54 | { |
49 | { |
Line 55... | Line 50... | ||
55 | struct ttm_buffer_object *bo = &buf->base; |
50 | struct ttm_buffer_object *bo = &buf->base; |
56 | int ret; |
51 | int ret; |
57 | 52 | ||
Line 58... | Line 53... | ||
58 | // ret = ttm_write_lock(&vmaster->lock, interruptible); |
53 | ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible); |
Line 59... | Line 54... | ||
59 | // if (unlikely(ret != 0)) |
54 | if (unlikely(ret != 0)) |
60 | // return ret; |
55 | return ret; |
61 | 56 | ||
Line 62... | Line 57... | ||
62 | vmw_execbuf_release_pinned_bo(dev_priv); |
57 | vmw_execbuf_release_pinned_bo(dev_priv); |
- | 58 | ||
- | 59 | ret = ttm_bo_reserve(bo, interruptible, false, false, NULL); |
|
Line 63... | Line 60... | ||
63 | 60 | if (unlikely(ret != 0)) |
|
Line 64... | Line 61... | ||
64 | ret = ttm_bo_reserve(bo, interruptible, false, false, NULL); |
61 | goto err; |
65 | if (unlikely(ret != 0)) |
62 | |
66 | goto err; |
63 | ret = ttm_bo_validate(bo, placement, interruptible, false); |
67 | 64 | if (!ret) |
|
Line 68... | Line 65... | ||
68 | ret = ttm_bo_validate(bo, placement, interruptible, false); |
65 | vmw_bo_pin_reserved(buf, true); |
69 | 66 | ||
70 | ttm_bo_unreserve(bo); |
67 | ttm_bo_unreserve(bo); |
71 | - | ||
72 | err: |
- | |
73 | // ttm_write_unlock(&vmaster->lock); |
68 | |
74 | return ret; |
69 | err: |
75 | } |
70 | ttm_write_unlock(&dev_priv->reservation_sem); |
76 | 71 | return ret; |
|
77 | /** |
72 | } |
78 | * vmw_dmabuf_to_vram_or_gmr - Move a buffer to vram or gmr. |
73 | |
79 | * |
74 | /** |
80 | * May only be called by the current master since it assumes that the |
75 | * vmw_dmabuf_pin_in_vram_or_gmr - Move a buffer to vram or gmr. |
81 | * master lock is the current master's lock. |
76 | * |
82 | * This function takes the master's lock in write mode. |
77 | * This function takes the reservation_sem in write mode. |
83 | * Flushes and unpins the query bo if @pin == true to avoid failures. |
78 | * Flushes and unpins the query bo to avoid failures. |
84 | * |
79 | * |
85 | * @dev_priv: Driver private. |
80 | * @dev_priv: Driver private. |
86 | * @buf: DMA buffer to move. |
81 | * @buf: DMA buffer to move. |
87 | * @pin: Pin buffer if true. |
82 | * @pin: Pin buffer if true. |
88 | * @interruptible: Use interruptible wait. |
83 | * @interruptible: Use interruptible wait. |
89 | * |
- | |
90 | * Returns |
84 | * |
Line 91... | Line 85... | ||
91 | * -ERESTARTSYS if interrupted by a signal. |
85 | * Returns |
92 | */ |
86 | * -ERESTARTSYS if interrupted by a signal. |
93 | int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv, |
87 | */ |
Line 94... | Line -... | ||
94 | struct vmw_dma_buffer *buf, |
- | |
95 | bool pin, bool interruptible) |
88 | int vmw_dmabuf_pin_in_vram_or_gmr(struct vmw_private *dev_priv, |
Line 96... | Line 89... | ||
96 | { |
89 | struct vmw_dma_buffer *buf, |
97 | struct ttm_buffer_object *bo = &buf->base; |
90 | bool interruptible) |
98 | struct ttm_placement *placement; |
91 | { |
Line 99... | Line -... | ||
99 | int ret; |
- | |
100 | - | ||
101 | // ret = ttm_write_lock(&vmaster->lock, interruptible); |
- | |
102 | // if (unlikely(ret != 0)) |
- | |
103 | // return ret; |
- | |
104 | - | ||
105 | if (pin) |
- | |
106 | vmw_execbuf_release_pinned_bo(dev_priv); |
- | |
107 | 92 | struct ttm_buffer_object *bo = &buf->base; |
|
108 | ret = ttm_bo_reserve(bo, interruptible, false, false, NULL); |
93 | int ret; |
109 | if (unlikely(ret != 0)) |
- | |
110 | goto err; |
- | |
111 | - | ||
112 | /** |
94 | |
113 | * Put BO in VRAM if there is space, otherwise as a GMR. |
95 | ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible); |
Line -... | Line 96... | ||
- | 96 | if (unlikely(ret != 0)) |
|
Line 114... | Line -... | ||
114 | * If there is no space in VRAM and GMR ids are all used up, |
- | |
115 | * start evicting GMRs to make room. If the DMA buffer can't be |
- | |
116 | * used as a GMR, this will return -ENOMEM. |
97 | return ret; |
117 | */ |
- | |
118 | - | ||
119 | if (pin) |
98 | |
120 | placement = &vmw_vram_gmr_ne_placement; |
- | |
121 | else |
- | |
122 | placement = &vmw_vram_gmr_placement; |
99 | vmw_execbuf_release_pinned_bo(dev_priv); |
Line 123... | Line -... | ||
123 | - | ||
124 | ret = ttm_bo_validate(bo, placement, interruptible, false); |
- | |
125 | if (likely(ret == 0) || ret == -ERESTARTSYS) |
- | |
126 | goto err_unreserve; |
100 | |
127 | 101 | ret = ttm_bo_reserve(bo, interruptible, false, false, NULL); |
|
128 | 102 | if (unlikely(ret != 0)) |
|
129 | /** |
103 | goto err; |
130 | * If that failed, try VRAM again, this time evicting |
104 | |
Line 131... | Line 105... | ||
131 | * previous contents. |
105 | ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, interruptible, |
132 | */ |
106 | false); |
133 | 107 | if (likely(ret == 0) || ret == -ERESTARTSYS) |
|
134 | if (pin) |
108 | goto out_unreserve; |
135 | placement = &vmw_vram_ne_placement; |
109 | |
136 | else |
- | |
137 | placement = &vmw_vram_placement; |
110 | ret = ttm_bo_validate(bo, &vmw_vram_placement, interruptible, false); |
138 | 111 | ||
139 | ret = ttm_bo_validate(bo, placement, interruptible, false); |
112 | out_unreserve: |
140 | - | ||
141 | err_unreserve: |
113 | if (!ret) |
142 | ttm_bo_unreserve(bo); |
114 | vmw_bo_pin_reserved(buf, true); |
143 | err: |
115 | |
144 | // ttm_write_unlock(&vmaster->lock); |
116 | ttm_bo_unreserve(bo); |
145 | return ret; |
117 | err: |
146 | } |
118 | ttm_write_unlock(&dev_priv->reservation_sem); |
147 | 119 | return ret; |
|
148 | /** |
120 | } |
149 | * vmw_dmabuf_to_vram - Move a buffer to vram. |
121 | |
150 | * |
- | |
151 | * May only be called by the current master since it assumes that the |
- | |
152 | * master lock is the current master's lock. |
- | |
153 | * This function takes the master's lock in write mode. |
- | |
154 | * |
- | |
155 | * @dev_priv: Driver private. |
- | |
156 | * @buf: DMA buffer to move. |
- | |
157 | * @pin: Pin buffer in vram if true. |
122 | /** |
158 | * @interruptible: Use interruptible wait. |
- | |
159 | * |
123 | * vmw_dmabuf_pin_in_vram - Move a buffer to vram. |
160 | * Returns |
124 | * |
Line 161... | Line 125... | ||
161 | * -ERESTARTSYS if interrupted by a signal. |
125 | * This function takes the reservation_sem in write mode. |
162 | */ |
126 | * Flushes and unpins the query bo to avoid failures. |
163 | int vmw_dmabuf_to_vram(struct vmw_private *dev_priv, |
127 | * |
164 | struct vmw_dma_buffer *buf, |
- | |
165 | bool pin, bool interruptible) |
- | |
166 | { |
128 | * @dev_priv: Driver private. |
167 | struct ttm_placement *placement; |
129 | * @buf: DMA buffer to move. |
168 | 130 | * @interruptible: Use interruptible wait. |
|
169 | if (pin) |
131 | * |
170 | placement = &vmw_vram_ne_placement; |
132 | * Returns |
171 | else |
- | |
172 | placement = &vmw_vram_placement; |
133 | * -ERESTARTSYS if interrupted by a signal. |
173 | 134 | */ |
|
174 | return vmw_dmabuf_to_placement(dev_priv, buf, |
135 | int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv, |
175 | placement, |
136 | struct vmw_dma_buffer *buf, |
176 | interruptible); |
137 | bool interruptible) |
177 | } |
138 | { |
178 | 139 | return vmw_dmabuf_pin_in_placement(dev_priv, buf, &vmw_vram_placement, |
|
179 | /** |
140 | interruptible); |
180 | * vmw_dmabuf_to_start_of_vram - Move a buffer to start of vram. |
141 | } |
181 | * |
142 | |
182 | * May only be called by the current master since it assumes that the |
143 | /** |
- | 144 | * vmw_dmabuf_pin_in_start_of_vram - Move a buffer to start of vram. |
|
183 | * master lock is the current master's lock. |
145 | * |
Line -... | Line 146... | ||
- | 146 | * This function takes the reservation_sem in write mode. |
|
184 | * This function takes the master's lock in write mode. |
147 | * Flushes and unpins the query bo to avoid failures. |
185 | * Flushes and unpins the query bo if @pin == true to avoid failures. |
148 | * |
186 | * |
149 | * @dev_priv: Driver private. |
187 | * @dev_priv: Driver private. |
150 | * @buf: DMA buffer to pin. |
188 | * @buf: DMA buffer to move. |
151 | * @interruptible: Use interruptible wait. |
189 | * @pin: Pin buffer in vram if true. |
152 | * |
190 | * @interruptible: Use interruptible wait. |
153 | * Returns |
191 | * |
154 | * -ERESTARTSYS if interrupted by a signal. |
192 | * Returns |
155 | */ |
Line 193... | Line -... | ||
193 | * -ERESTARTSYS if interrupted by a signal. |
- | |
194 | */ |
156 | int vmw_dmabuf_pin_in_start_of_vram(struct vmw_private *dev_priv, |
195 | int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv, |
157 | struct vmw_dma_buffer *buf, |
196 | struct vmw_dma_buffer *buf, |
158 | bool interruptible) |
197 | bool pin, bool interruptible) |
159 | { |
Line -... | Line 160... | ||
- | 160 | struct ttm_buffer_object *bo = &buf->base; |
|
198 | { |
161 | struct ttm_placement placement; |
- | 162 | struct ttm_place place; |
|
- | 163 | int ret = 0; |
|
- | 164 | ||
199 | struct ttm_buffer_object *bo = &buf->base; |
165 | place = vmw_vram_placement.placement[0]; |
200 | struct ttm_placement placement; |
166 | place.lpfn = bo->num_pages; |
201 | int ret = 0; |
167 | placement.num_placement = 1; |
202 | 168 | placement.placement = &place; |
|
Line 203... | Line 169... | ||
203 | if (pin) |
169 | placement.num_busy_placement = 1; |
Line 204... | Line 170... | ||
204 | placement = vmw_vram_ne_placement; |
170 | placement.busy_placement = &place; |
205 | else |
171 | |
- | 172 | ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible); |
|
- | 173 | if (unlikely(ret != 0)) |
|
Line 206... | Line 174... | ||
206 | placement = vmw_vram_placement; |
174 | return ret; |
207 | placement.lpfn = bo->num_pages; |
175 | |
208 | 176 | vmw_execbuf_release_pinned_bo(dev_priv); |
|
Line 209... | Line 177... | ||
209 | // ret = ttm_write_lock(&vmaster->lock, interruptible); |
177 | ret = ttm_bo_reserve(bo, interruptible, false, false, NULL); |
210 | // if (unlikely(ret != 0)) |
178 | if (unlikely(ret != 0)) |
Line 211... | Line -... | ||
211 | // return ret; |
- | |
212 | 179 | goto err_unlock; |
|
213 | if (pin) |
180 | |
214 | vmw_execbuf_release_pinned_bo(dev_priv); |
181 | /* |
215 | ret = ttm_bo_reserve(bo, interruptible, false, false, NULL); |
- | |
216 | if (unlikely(ret != 0)) |
- | |
217 | goto err_unlock; |
182 | * Is this buffer already in vram but not at the start of it? |
218 | 183 | * In that case, evict it first because TTM isn't good at handling |
|
219 | /* Is this buffer already in vram but not at the start of it? */ |
184 | * that situation. |
220 | if (bo->mem.mem_type == TTM_PL_VRAM && |
185 | */ |
221 | bo->mem.start < bo->num_pages && |
186 | if (bo->mem.mem_type == TTM_PL_VRAM && |
222 | bo->mem.start > 0) |
187 | bo->mem.start < bo->num_pages && |
Line 251... | Line 216... | ||
251 | */ |
216 | */ |
252 | int vmw_dmabuf_unpin(struct vmw_private *dev_priv, |
217 | int vmw_dmabuf_unpin(struct vmw_private *dev_priv, |
253 | struct vmw_dma_buffer *buf, |
218 | struct vmw_dma_buffer *buf, |
254 | bool interruptible) |
219 | bool interruptible) |
255 | { |
220 | { |
- | 221 | struct ttm_buffer_object *bo = &buf->base; |
|
- | 222 | int ret; |
|
256 | /* |
223 | |
257 | * We could in theory early out if the buffer is |
224 | ret = ttm_read_lock(&dev_priv->reservation_sem, interruptible); |
258 | * unpinned but we need to lock and reserve the buffer |
225 | if (unlikely(ret != 0)) |
259 | * anyways so we don't gain much by that. |
226 | return ret; |
260 | */ |
227 | |
261 | return vmw_dmabuf_to_placement(dev_priv, buf, |
228 | ret = ttm_bo_reserve(bo, interruptible, false, false, NULL); |
262 | &vmw_evictable_placement, |
229 | if (unlikely(ret != 0)) |
263 | interruptible); |
230 | goto err; |
264 | } |
- | |
Line -... | Line 231... | ||
- | 231 | ||
- | 232 | vmw_bo_pin_reserved(buf, false); |
|
- | 233 | ||
- | 234 | ttm_bo_unreserve(bo); |
|
- | 235 | ||
- | 236 | err: |
|
- | 237 | ttm_read_unlock(&dev_priv->reservation_sem); |
|
- | 238 | return ret; |
|
Line 265... | Line 239... | ||
265 | 239 | } |
|
266 | 240 | ||
267 | /** |
241 | /** |
268 | * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement |
242 | * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement |
Line 283... | Line 257... | ||
283 | } |
257 | } |
284 | } |
258 | } |
Line 285... | Line 259... | ||
285 | 259 | ||
286 | 260 | ||
287 | /** |
261 | /** |
288 | * vmw_bo_pin - Pin or unpin a buffer object without moving it. |
262 | * vmw_bo_pin_reserved - Pin or unpin a buffer object without moving it. |
289 | * |
263 | * |
290 | * @bo: The buffer object. Must be reserved. |
264 | * @vbo: The buffer object. Must be reserved. |
291 | * @pin: Whether to pin or unpin. |
265 | * @pin: Whether to pin or unpin. |
292 | * |
266 | * |
293 | */ |
267 | */ |
294 | void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) |
268 | void vmw_bo_pin_reserved(struct vmw_dma_buffer *vbo, bool pin) |
295 | { |
269 | { |
- | 270 | struct ttm_place pl; |
|
296 | uint32_t pl_flags; |
271 | struct ttm_placement placement; |
297 | struct ttm_placement placement; |
272 | struct ttm_buffer_object *bo = &vbo->base; |
Line 298... | Line 273... | ||
298 | uint32_t old_mem_type = bo->mem.mem_type; |
273 | uint32_t old_mem_type = bo->mem.mem_type; |
Line -... | Line 274... | ||
- | 274 | int ret; |
|
- | 275 | ||
- | 276 | lockdep_assert_held(&bo->resv->lock.base); |
|
- | 277 | ||
- | 278 | if (pin) { |
|
- | 279 | if (vbo->pin_count++ > 0) |
|
- | 280 | return; |
|
- | 281 | } else { |
|
- | 282 | WARN_ON(vbo->pin_count <= 0); |
|
- | 283 | if (--vbo->pin_count > 0) |
|
- | 284 | return; |
|
299 | int ret; |
285 | } |
300 | 286 | ||
301 | lockdep_assert_held(&bo->resv->lock.base); |
287 | pl.fpfn = 0; |
302 | 288 | pl.lpfn = 0; |
|
Line 303... | Line 289... | ||
303 | pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | VMW_PL_FLAG_MOB |
289 | pl.flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | VMW_PL_FLAG_MOB |
304 | | TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED; |
290 | | TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED; |
305 | if (pin) |
291 | if (pin) |
Line 306... | Line 292... | ||
306 | pl_flags |= TTM_PL_FLAG_NO_EVICT; |
292 | pl.flags |= TTM_PL_FLAG_NO_EVICT; |
Line 307... | Line 293... | ||
307 | 293 | ||
308 | memset(&placement, 0, sizeof(placement)); |
294 | memset(&placement, 0, sizeof(placement)); |