Rev 3262 | Rev 4103 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3262 | Rev 4065 | ||
---|---|---|---|
Line 31... | Line 31... | ||
31 | #define _TTM_BO_DRIVER_H_ |
31 | #define _TTM_BO_DRIVER_H_ |
Line 32... | Line 32... | ||
32 | 32 | ||
33 | #include |
33 | #include |
34 | #include |
34 | #include |
- | 35 | #include |
|
35 | #include |
36 | #include |
36 | #include |
37 | #include |
37 | #include |
38 | #include |
38 | //#include |
39 | //#include |
39 | //#include |
40 | //#include |
Line -... | Line 41... | ||
- | 41 | #include |
|
- | 42 | ||
40 | #include |
43 | struct ww_acquire_ctx; |
41 | 44 | ||
42 | struct ttm_backend_func { |
45 | struct ttm_backend_func { |
43 | /** |
46 | /** |
44 | * struct ttm_backend_func member bind |
47 | * struct ttm_backend_func member bind |
Line 776... | Line 779... | ||
776 | * ttm_bo_reserve: |
779 | * ttm_bo_reserve: |
777 | * |
780 | * |
778 | * @bo: A pointer to a struct ttm_buffer_object. |
781 | * @bo: A pointer to a struct ttm_buffer_object. |
779 | * @interruptible: Sleep interruptible if waiting. |
782 | * @interruptible: Sleep interruptible if waiting. |
780 | * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. |
783 | * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. |
781 | * @use_sequence: If @bo is already reserved, Only sleep waiting for |
784 | * @use_ticket: If @bo is already reserved, Only sleep waiting for |
782 | * it to become unreserved if @sequence < (@bo)->sequence. |
785 | * it to become unreserved if @ticket->stamp is older. |
783 | * |
786 | * |
784 | * Locks a buffer object for validation. (Or prevents other processes from |
787 | * Locks a buffer object for validation. (Or prevents other processes from |
785 | * locking it for validation) and removes it from lru lists, while taking |
788 | * locking it for validation) and removes it from lru lists, while taking |
786 | * a number of measures to prevent deadlocks. |
789 | * a number of measures to prevent deadlocks. |
787 | * |
790 | * |
788 | * Deadlocks may occur when two processes try to reserve multiple buffers in |
791 | * Deadlocks may occur when two processes try to reserve multiple buffers in |
789 | * different order, either by will or as a result of a buffer being evicted |
792 | * different order, either by will or as a result of a buffer being evicted |
790 | * to make room for a buffer already reserved. (Buffers are reserved before |
793 | * to make room for a buffer already reserved. (Buffers are reserved before |
791 | * they are evicted). The following algorithm prevents such deadlocks from |
794 | * they are evicted). The following algorithm prevents such deadlocks from |
792 | * occurring: |
795 | * occurring: |
793 | * 1) Buffers are reserved with the lru spinlock held. Upon successful |
- | |
794 | * reservation they are removed from the lru list. This stops a reserved buffer |
- | |
795 | * from being evicted. However the lru spinlock is released between the time |
- | |
796 | * a buffer is selected for eviction and the time it is reserved. |
- | |
797 | * Therefore a check is made when a buffer is reserved for eviction, that it |
- | |
798 | * is still the first buffer in the lru list, before it is removed from the |
- | |
799 | * list. @check_lru == 1 forces this check. If it fails, the function returns |
- | |
800 | * -EINVAL, and the caller should then choose a new buffer to evict and repeat |
- | |
801 | * the procedure. |
- | |
802 | * 2) Processes attempting to reserve multiple buffers other than for eviction, |
796 | * Processes attempting to reserve multiple buffers other than for eviction, |
803 | * (typically execbuf), should first obtain a unique 32-bit |
797 | * (typically execbuf), should first obtain a unique 32-bit |
804 | * validation sequence number, |
798 | * validation sequence number, |
805 | * and call this function with @use_sequence == 1 and @sequence == the unique |
799 | * and call this function with @use_ticket == 1 and @ticket->stamp == the unique |
806 | * sequence number. If upon call of this function, the buffer object is already |
800 | * sequence number. If upon call of this function, the buffer object is already |
807 | * reserved, the validation sequence is checked against the validation |
801 | * reserved, the validation sequence is checked against the validation |
808 | * sequence of the process currently reserving the buffer, |
802 | * sequence of the process currently reserving the buffer, |
809 | * and if the current validation sequence is greater than that of the process |
803 | * and if the current validation sequence is greater than that of the process |
810 | * holding the reservation, the function returns -EAGAIN. Otherwise it sleeps |
804 | * holding the reservation, the function returns -EAGAIN. Otherwise it sleeps |
Line 815... | Line 809... | ||
815 | * then rerun the validation with the same validation sequence. This procedure |
809 | * then rerun the validation with the same validation sequence. This procedure |
816 | * will always guarantee that the process with the lowest validation sequence |
810 | * will always guarantee that the process with the lowest validation sequence |
817 | * will eventually succeed, preventing both deadlocks and starvation. |
811 | * will eventually succeed, preventing both deadlocks and starvation. |
818 | * |
812 | * |
819 | * Returns: |
813 | * Returns: |
820 | * -EAGAIN: The reservation may cause a deadlock. |
814 | * -EDEADLK: The reservation may cause a deadlock. |
821 | * Release all buffer reservations, wait for @bo to become unreserved and |
815 | * Release all buffer reservations, wait for @bo to become unreserved and |
822 | * try again. (only if use_sequence == 1). |
816 | * try again. (only if use_sequence == 1). |
823 | * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by |
817 | * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by |
824 | * a signal. Release all buffer reservations and return to user-space. |
818 | * a signal. Release all buffer reservations and return to user-space. |
825 | * -EBUSY: The function needed to sleep, but @no_wait was true |
819 | * -EBUSY: The function needed to sleep, but @no_wait was true |
826 | * -EDEADLK: Bo already reserved using @sequence. This error code will only |
820 | * -EALREADY: Bo already reserved using @ticket. This error code will only |
827 | * be returned if @use_sequence is set to true. |
821 | * be returned if @use_ticket is set to true. |
828 | */ |
822 | */ |
829 | extern int ttm_bo_reserve(struct ttm_buffer_object *bo, |
823 | static inline int ttm_bo_reserve(struct ttm_buffer_object *bo, |
830 | bool interruptible, |
824 | bool interruptible, |
831 | bool no_wait, bool use_sequence, uint32_t sequence); |
825 | bool no_wait, bool use_ticket, |
- | 826 | struct ww_acquire_ctx *ticket) |
|
- | 827 | { |
|
- | 828 | int ret; |
|
- | 829 | ||
- | 830 | WARN_ON(!atomic_read(&bo->kref.refcount)); |
|
Line -... | Line 831... | ||
- | 831 | ||
- | 832 | ret = ttm_bo_reserve_nolru(bo, interruptible, no_wait, use_ticket, |
|
- | 833 | ticket); |
|
- | 834 | if (likely(ret == 0)) |
|
- | 835 | ttm_bo_del_sub_from_lru(bo); |
|
- | 836 | ||
- | 837 | return ret; |
|
Line 832... | Line 838... | ||
832 | 838 | } |
|
833 | 839 | ||
834 | /** |
- | |
835 | * ttm_bo_reserve_locked: |
840 | /** |
836 | * |
841 | * ttm_bo_reserve_slowpath: |
837 | * @bo: A pointer to a struct ttm_buffer_object. |
- | |
838 | * @interruptible: Sleep interruptible if waiting. |
842 | * @bo: A pointer to a struct ttm_buffer_object. |
839 | * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. |
- | |
840 | * @use_sequence: If @bo is already reserved, Only sleep waiting for |
- | |
841 | * it to become unreserved if @sequence < (@bo)->sequence. |
- | |
842 | * |
- | |
843 | * Must be called with struct ttm_bo_global::lru_lock held, |
- | |
844 | * and will not remove reserved buffers from the lru lists. |
- | |
845 | * The function may release the LRU spinlock if it needs to sleep. |
843 | * @interruptible: Sleep interruptible if waiting. |
846 | * Otherwise identical to ttm_bo_reserve. |
- | |
847 | * |
844 | * @sequence: Set (@bo)->sequence to this value after lock |
848 | * Returns: |
845 | * |
849 | * -EAGAIN: The reservation may cause a deadlock. |
- | |
850 | * Release all buffer reservations, wait for @bo to become unreserved and |
- | |
851 | * try again. (only if use_sequence == 1). |
- | |
852 | * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by |
- | |
853 | * a signal. Release all buffer reservations and return to user-space. |
- | |
854 | * -EBUSY: The function needed to sleep, but @no_wait was true |
846 | * This is called after ttm_bo_reserve returns -EAGAIN and we backed off |
855 | * -EDEADLK: Bo already reserved using @sequence. This error code will only |
847 | * from all our other reservations. Because there are no other reservations |
856 | * be returned if @use_sequence is set to true. |
848 | * held by us, this function cannot deadlock any more. |
857 | */ |
849 | */ |
858 | extern int ttm_bo_reserve_locked(struct ttm_buffer_object *bo, |
850 | static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, |
- | 851 | bool interruptible, |
|
859 | bool interruptible, |
852 | struct ww_acquire_ctx *ticket) |
Line -... | Line 853... | ||
- | 853 | { |
|
860 | bool no_wait, bool use_sequence, |
854 | int ret = 0; |
861 | uint32_t sequence); |
855 | |
- | 856 | WARN_ON(!atomic_read(&bo->kref.refcount)); |
|
- | 857 | ||
862 | 858 | if (interruptible) |
|
863 | /** |
859 | ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock, |
864 | * ttm_bo_unreserve |
860 | ticket); |
- | 861 | else |
|
- | 862 | ww_mutex_lock_slow(&bo->resv->lock, ticket); |
|
865 | * |
863 | |
- | 864 | if (likely(ret == 0)) |
|
866 | * @bo: A pointer to a struct ttm_buffer_object. |
865 | ttm_bo_del_sub_from_lru(bo); |
867 | * |
866 | else if (ret == -EINTR) |
- | 867 | ret = -ERESTARTSYS; |
|
Line 868... | Line 868... | ||
868 | * Unreserve a previous reservation of @bo. |
868 | |
869 | */ |
869 | return ret; |
870 | extern void ttm_bo_unreserve(struct ttm_buffer_object *bo); |
- | |
871 | 870 | } |
|
- | 871 | ||
872 | /** |
872 | /** |
873 | * ttm_bo_unreserve_locked |
873 | * ttm_bo_unreserve_ticket |
874 | * |
- | |
875 | * @bo: A pointer to a struct ttm_buffer_object. |
874 | * @bo: A pointer to a struct ttm_buffer_object. |
876 | * |
875 | * @ticket: ww_acquire_ctx used for reserving |
- | 876 | * |
|
- | 877 | * Unreserve a previous reservation of @bo made with @ticket. |
|
- | 878 | */ |
|
- | 879 | static inline void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo, |
|
- | 880 | struct ww_acquire_ctx *t) |
|
- | 881 | { |
|
- | 882 | if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) { |
|
- | 883 | spin_lock(&bo->glob->lru_lock); |
|
- | 884 | ttm_bo_add_to_lru(bo); |
|
Line 877... | Line 885... | ||
877 | * Unreserve a previous reservation of @bo. |
885 | spin_unlock(&bo->glob->lru_lock); |
878 | * Needs to be called with struct ttm_bo_global::lru_lock held. |
886 | } |
879 | */ |
887 | ww_mutex_unlock(&bo->resv->lock); |
880 | extern void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo); |
888 | } |
881 | 889 | ||
882 | /** |
- | |
883 | * ttm_bo_wait_unreserved |
- | |
884 | * |
890 | /** |
885 | * @bo: A pointer to a struct ttm_buffer_object. |
891 | * ttm_bo_unreserve |
886 | * |
892 | * |
- | 893 | * @bo: A pointer to a struct ttm_buffer_object. |
|
887 | * Wait for a struct ttm_buffer_object to become unreserved. |
894 | * |
- | 895 | * Unreserve a previous reservation of @bo. |
|
Line 888... | Line 896... | ||
888 | * This is typically used in the execbuf code to relax cpu-usage when |
896 | */ |
889 | * a potential deadlock condition backoff. |
897 | static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) |
890 | */ |
898 | { |
Line -... | Line 899... | ||
- | 899 | ttm_bo_unreserve_ticket(bo, NULL); |
|
- | 900 | } |
|
- | 901 | ||
- | 902 | /* |
|
891 | extern int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, |
903 | * ttm_bo_util.c |
892 | bool interruptible); |
904 | */ |
893 | 905 | ||
894 | /* |
906 | int ttm_mem_io_reserve(struct ttm_bo_device *bdev, |
895 | * ttm_bo_util.c |
907 | struct ttm_mem_reg *mem); |