diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_gtt.h')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.h | 183 |
1 files changed, 150 insertions, 33 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index aa5f31d1c2ed..cc56206a1600 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h | |||
@@ -36,6 +36,8 @@ | |||
36 | 36 | ||
37 | #include <linux/io-mapping.h> | 37 | #include <linux/io-mapping.h> |
38 | 38 | ||
39 | #include "i915_gem_request.h" | ||
40 | |||
39 | struct drm_i915_file_private; | 41 | struct drm_i915_file_private; |
40 | 42 | ||
41 | typedef uint32_t gen6_pte_t; | 43 | typedef uint32_t gen6_pte_t; |
@@ -178,12 +180,32 @@ struct i915_vma { | |||
178 | struct drm_i915_gem_object *obj; | 180 | struct drm_i915_gem_object *obj; |
179 | struct i915_address_space *vm; | 181 | struct i915_address_space *vm; |
180 | void __iomem *iomap; | 182 | void __iomem *iomap; |
183 | u64 size; | ||
184 | |||
185 | unsigned int flags; | ||
186 | /** | ||
187 | * How many users have pinned this object in GTT space. The following | ||
188 | * users can each hold at most one reference: pwrite/pread, execbuffer | ||
189 | * (objects are not allowed multiple times for the same batchbuffer), | ||
190 | * and the framebuffer code. When switching/pageflipping, the | ||
191 | * framebuffer code has at most two buffers pinned per crtc. | ||
192 | * | ||
193 | * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3 | ||
194 | * bits with absolutely no headroom. So use 4 bits. | ||
195 | */ | ||
196 | #define I915_VMA_PIN_MASK 0xf | ||
197 | #define I915_VMA_PIN_OVERFLOW BIT(5) | ||
181 | 198 | ||
182 | /** Flags and address space this VMA is bound to */ | 199 | /** Flags and address space this VMA is bound to */ |
183 | #define GLOBAL_BIND (1<<0) | 200 | #define I915_VMA_GLOBAL_BIND BIT(6) |
184 | #define LOCAL_BIND (1<<1) | 201 | #define I915_VMA_LOCAL_BIND BIT(7) |
185 | unsigned int bound : 4; | 202 | #define I915_VMA_BIND_MASK (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND | I915_VMA_PIN_OVERFLOW) |
186 | bool is_ggtt : 1; | 203 | |
204 | #define I915_VMA_GGTT BIT(8) | ||
205 | #define I915_VMA_CLOSED BIT(9) | ||
206 | |||
207 | unsigned int active; | ||
208 | struct i915_gem_active last_read[I915_NUM_ENGINES]; | ||
187 | 209 | ||
188 | /** | 210 | /** |
189 | * Support different GGTT views into the same object. | 211 | * Support different GGTT views into the same object. |
@@ -208,20 +230,46 @@ struct i915_vma { | |||
208 | struct hlist_node exec_node; | 230 | struct hlist_node exec_node; |
209 | unsigned long exec_handle; | 231 | unsigned long exec_handle; |
210 | struct drm_i915_gem_exec_object2 *exec_entry; | 232 | struct drm_i915_gem_exec_object2 *exec_entry; |
211 | |||
212 | /** | ||
213 | * How many users have pinned this object in GTT space. The following | ||
214 | * users can each hold at most one reference: pwrite/pread, execbuffer | ||
215 | * (objects are not allowed multiple times for the same batchbuffer), | ||
216 | * and the framebuffer code. When switching/pageflipping, the | ||
217 | * framebuffer code has at most two buffers pinned per crtc. | ||
218 | * | ||
219 | * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3 | ||
220 | * bits with absolutely no headroom. So use 4 bits. */ | ||
221 | unsigned int pin_count:4; | ||
222 | #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf | ||
223 | }; | 233 | }; |
224 | 234 | ||
235 | static inline bool i915_vma_is_ggtt(const struct i915_vma *vma) | ||
236 | { | ||
237 | return vma->flags & I915_VMA_GGTT; | ||
238 | } | ||
239 | |||
240 | static inline bool i915_vma_is_closed(const struct i915_vma *vma) | ||
241 | { | ||
242 | return vma->flags & I915_VMA_CLOSED; | ||
243 | } | ||
244 | |||
245 | static inline unsigned int i915_vma_get_active(const struct i915_vma *vma) | ||
246 | { | ||
247 | return vma->active; | ||
248 | } | ||
249 | |||
250 | static inline bool i915_vma_is_active(const struct i915_vma *vma) | ||
251 | { | ||
252 | return i915_vma_get_active(vma); | ||
253 | } | ||
254 | |||
255 | static inline void i915_vma_set_active(struct i915_vma *vma, | ||
256 | unsigned int engine) | ||
257 | { | ||
258 | vma->active |= BIT(engine); | ||
259 | } | ||
260 | |||
261 | static inline void i915_vma_clear_active(struct i915_vma *vma, | ||
262 | unsigned int engine) | ||
263 | { | ||
264 | vma->active &= ~BIT(engine); | ||
265 | } | ||
266 | |||
267 | static inline bool i915_vma_has_active_engine(const struct i915_vma *vma, | ||
268 | unsigned int engine) | ||
269 | { | ||
270 | return vma->active & BIT(engine); | ||
271 | } | ||
272 | |||
225 | struct i915_page_dma { | 273 | struct i915_page_dma { |
226 | struct page *page; | 274 | struct page *page; |
227 | union { | 275 | union { |
@@ -272,11 +320,20 @@ struct i915_pml4 { | |||
272 | struct i915_address_space { | 320 | struct i915_address_space { |
273 | struct drm_mm mm; | 321 | struct drm_mm mm; |
274 | struct drm_device *dev; | 322 | struct drm_device *dev; |
323 | /* Every address space belongs to a struct file - except for the global | ||
324 | * GTT that is owned by the driver (and so @file is set to NULL). In | ||
325 | * principle, no information should leak from one context to another | ||
326 | * (or between files/processes etc) unless explicitly shared by the | ||
327 | * owner. Tracking the owner is important in order to free up per-file | ||
328 | * objects along with the file, to aide resource tracking, and to | ||
329 | * assign blame. | ||
330 | */ | ||
331 | struct drm_i915_file_private *file; | ||
275 | struct list_head global_link; | 332 | struct list_head global_link; |
276 | u64 start; /* Start offset always 0 for dri2 */ | 333 | u64 start; /* Start offset always 0 for dri2 */ |
277 | u64 total; /* size addr space maps (ex. 2GB for ggtt) */ | 334 | u64 total; /* size addr space maps (ex. 2GB for ggtt) */ |
278 | 335 | ||
279 | bool is_ggtt; | 336 | bool closed; |
280 | 337 | ||
281 | struct i915_page_scratch *scratch_page; | 338 | struct i915_page_scratch *scratch_page; |
282 | struct i915_page_table *scratch_pt; | 339 | struct i915_page_table *scratch_pt; |
@@ -306,6 +363,13 @@ struct i915_address_space { | |||
306 | */ | 363 | */ |
307 | struct list_head inactive_list; | 364 | struct list_head inactive_list; |
308 | 365 | ||
366 | /** | ||
367 | * List of vma that have been unbound. | ||
368 | * | ||
369 | * A reference is not held on the buffer while on this list. | ||
370 | */ | ||
371 | struct list_head unbound_list; | ||
372 | |||
309 | /* FIXME: Need a more generic return type */ | 373 | /* FIXME: Need a more generic return type */ |
310 | gen6_pte_t (*pte_encode)(dma_addr_t addr, | 374 | gen6_pte_t (*pte_encode)(dma_addr_t addr, |
311 | enum i915_cache_level level, | 375 | enum i915_cache_level level, |
@@ -338,7 +402,7 @@ struct i915_address_space { | |||
338 | u32 flags); | 402 | u32 flags); |
339 | }; | 403 | }; |
340 | 404 | ||
341 | #define i915_is_ggtt(V) ((V)->is_ggtt) | 405 | #define i915_is_ggtt(V) (!(V)->file) |
342 | 406 | ||
343 | /* The Graphics Translation Table is the way in which GEN hardware translates a | 407 | /* The Graphics Translation Table is the way in which GEN hardware translates a |
344 | * Graphics Virtual Address into a Physical Address. In addition to the normal | 408 | * Graphics Virtual Address into a Physical Address. In addition to the normal |
@@ -354,7 +418,6 @@ struct i915_ggtt { | |||
354 | size_t stolen_usable_size; /* Total size minus BIOS reserved */ | 418 | size_t stolen_usable_size; /* Total size minus BIOS reserved */ |
355 | size_t stolen_reserved_base; | 419 | size_t stolen_reserved_base; |
356 | size_t stolen_reserved_size; | 420 | size_t stolen_reserved_size; |
357 | size_t size; /* Total size of Global GTT */ | ||
358 | u64 mappable_end; /* End offset that we can CPU map */ | 421 | u64 mappable_end; /* End offset that we can CPU map */ |
359 | struct io_mapping *mappable; /* Mapping to our CPU mappable region */ | 422 | struct io_mapping *mappable; /* Mapping to our CPU mappable region */ |
360 | phys_addr_t mappable_base; /* PA of our GMADR */ | 423 | phys_addr_t mappable_base; /* PA of our GMADR */ |
@@ -365,8 +428,6 @@ struct i915_ggtt { | |||
365 | bool do_idle_maps; | 428 | bool do_idle_maps; |
366 | 429 | ||
367 | int mtrr; | 430 | int mtrr; |
368 | |||
369 | int (*probe)(struct i915_ggtt *ggtt); | ||
370 | }; | 431 | }; |
371 | 432 | ||
372 | struct i915_hw_ppgtt { | 433 | struct i915_hw_ppgtt { |
@@ -380,8 +441,6 @@ struct i915_hw_ppgtt { | |||
380 | struct i915_page_directory pd; /* GEN6-7 */ | 441 | struct i915_page_directory pd; /* GEN6-7 */ |
381 | }; | 442 | }; |
382 | 443 | ||
383 | struct drm_i915_file_private *file_priv; | ||
384 | |||
385 | gen6_pte_t __iomem *pd_addr; | 444 | gen6_pte_t __iomem *pd_addr; |
386 | 445 | ||
387 | int (*enable)(struct i915_hw_ppgtt *ppgtt); | 446 | int (*enable)(struct i915_hw_ppgtt *ppgtt); |
@@ -521,14 +580,15 @@ i915_page_dir_dma_addr(const struct i915_hw_ppgtt *ppgtt, const unsigned n) | |||
521 | px_dma(ppgtt->base.scratch_pd); | 580 | px_dma(ppgtt->base.scratch_pd); |
522 | } | 581 | } |
523 | 582 | ||
524 | int i915_ggtt_init_hw(struct drm_device *dev); | 583 | int i915_ggtt_probe_hw(struct drm_i915_private *dev_priv); |
525 | int i915_ggtt_enable_hw(struct drm_device *dev); | 584 | int i915_ggtt_init_hw(struct drm_i915_private *dev_priv); |
526 | void i915_gem_init_ggtt(struct drm_device *dev); | 585 | int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv); |
527 | void i915_ggtt_cleanup_hw(struct drm_device *dev); | 586 | int i915_gem_init_ggtt(struct drm_i915_private *dev_priv); |
587 | void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv); | ||
528 | 588 | ||
529 | int i915_ppgtt_init_hw(struct drm_device *dev); | 589 | int i915_ppgtt_init_hw(struct drm_device *dev); |
530 | void i915_ppgtt_release(struct kref *kref); | 590 | void i915_ppgtt_release(struct kref *kref); |
531 | struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_device *dev, | 591 | struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv, |
532 | struct drm_i915_file_private *fpriv); | 592 | struct drm_i915_file_private *fpriv); |
533 | static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt) | 593 | static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt) |
534 | { | 594 | { |
@@ -562,9 +622,66 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a, | |||
562 | return true; | 622 | return true; |
563 | } | 623 | } |
564 | 624 | ||
565 | size_t | 625 | /* Flags used by pin/bind&friends. */ |
566 | i915_ggtt_view_size(struct drm_i915_gem_object *obj, | 626 | #define PIN_NONBLOCK BIT(0) |
567 | const struct i915_ggtt_view *view); | 627 | #define PIN_MAPPABLE BIT(1) |
628 | #define PIN_ZONE_4G BIT(2) | ||
629 | |||
630 | #define PIN_MBZ BIT(5) /* I915_VMA_PIN_OVERFLOW */ | ||
631 | #define PIN_GLOBAL BIT(6) /* I915_VMA_GLOBAL_BIND */ | ||
632 | #define PIN_USER BIT(7) /* I915_VMA_LOCAL_BIND */ | ||
633 | #define PIN_UPDATE BIT(8) | ||
634 | |||
635 | #define PIN_HIGH BIT(9) | ||
636 | #define PIN_OFFSET_BIAS BIT(10) | ||
637 | #define PIN_OFFSET_FIXED BIT(11) | ||
638 | #define PIN_OFFSET_MASK (~4095) | ||
639 | |||
640 | int __i915_vma_do_pin(struct i915_vma *vma, | ||
641 | u64 size, u64 alignment, u64 flags); | ||
642 | static inline int __must_check | ||
643 | i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) | ||
644 | { | ||
645 | BUILD_BUG_ON(PIN_MBZ != I915_VMA_PIN_OVERFLOW); | ||
646 | BUILD_BUG_ON(PIN_GLOBAL != I915_VMA_GLOBAL_BIND); | ||
647 | BUILD_BUG_ON(PIN_USER != I915_VMA_LOCAL_BIND); | ||
648 | |||
649 | /* Pin early to prevent the shrinker/eviction logic from destroying | ||
650 | * our vma as we insert and bind. | ||
651 | */ | ||
652 | if (likely(((++vma->flags ^ flags) & I915_VMA_BIND_MASK) == 0)) | ||
653 | return 0; | ||
654 | |||
655 | return __i915_vma_do_pin(vma, size, alignment, flags); | ||
656 | } | ||
657 | |||
658 | static inline int i915_vma_pin_count(const struct i915_vma *vma) | ||
659 | { | ||
660 | return vma->flags & I915_VMA_PIN_MASK; | ||
661 | } | ||
662 | |||
663 | static inline bool i915_vma_is_pinned(const struct i915_vma *vma) | ||
664 | { | ||
665 | return i915_vma_pin_count(vma); | ||
666 | } | ||
667 | |||
668 | static inline void __i915_vma_pin(struct i915_vma *vma) | ||
669 | { | ||
670 | vma->flags++; | ||
671 | GEM_BUG_ON(vma->flags & I915_VMA_PIN_OVERFLOW); | ||
672 | } | ||
673 | |||
674 | static inline void __i915_vma_unpin(struct i915_vma *vma) | ||
675 | { | ||
676 | GEM_BUG_ON(!i915_vma_is_pinned(vma)); | ||
677 | vma->flags--; | ||
678 | } | ||
679 | |||
680 | static inline void i915_vma_unpin(struct i915_vma *vma) | ||
681 | { | ||
682 | GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); | ||
683 | __i915_vma_unpin(vma); | ||
684 | } | ||
568 | 685 | ||
569 | /** | 686 | /** |
570 | * i915_vma_pin_iomap - calls ioremap_wc to map the GGTT VMA via the aperture | 687 | * i915_vma_pin_iomap - calls ioremap_wc to map the GGTT VMA via the aperture |
@@ -580,6 +697,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj, | |||
580 | * Returns a valid iomapped pointer or ERR_PTR. | 697 | * Returns a valid iomapped pointer or ERR_PTR. |
581 | */ | 698 | */ |
582 | void __iomem *i915_vma_pin_iomap(struct i915_vma *vma); | 699 | void __iomem *i915_vma_pin_iomap(struct i915_vma *vma); |
700 | #define IO_ERR_PTR(x) ((void __iomem *)ERR_PTR(x)) | ||
583 | 701 | ||
584 | /** | 702 | /** |
585 | * i915_vma_unpin_iomap - unpins the mapping returned from i915_vma_iomap | 703 | * i915_vma_unpin_iomap - unpins the mapping returned from i915_vma_iomap |
@@ -593,9 +711,8 @@ void __iomem *i915_vma_pin_iomap(struct i915_vma *vma); | |||
593 | static inline void i915_vma_unpin_iomap(struct i915_vma *vma) | 711 | static inline void i915_vma_unpin_iomap(struct i915_vma *vma) |
594 | { | 712 | { |
595 | lockdep_assert_held(&vma->vm->dev->struct_mutex); | 713 | lockdep_assert_held(&vma->vm->dev->struct_mutex); |
596 | GEM_BUG_ON(vma->pin_count == 0); | ||
597 | GEM_BUG_ON(vma->iomap == NULL); | 714 | GEM_BUG_ON(vma->iomap == NULL); |
598 | vma->pin_count--; | 715 | i915_vma_unpin(vma); |
599 | } | 716 | } |
600 | 717 | ||
601 | #endif | 718 | #endif |