diff options
author | Dave Airlie <airlied@linux.ie> | 2009-09-14 21:12:56 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2009-09-15 19:15:39 -0400 |
commit | ecb114a128d150422d22eda238cb812f6b20bf39 (patch) | |
tree | 6cd09599363f9760fed8a210c576c984cbbeec18 /drivers/gpu/drm/radeon/radeon_ring.c | |
parent | 42dea5ddb56fe10e1d9a7840ddcb1df97a208a99 (diff) |
drm/radeon/kms: IB locking dumps out a lockdep ordering issue
We sometimes lock IB then the ring and sometimes the ring then
the IB. This is mostly due to the IB locking not being well defined
about what data in the structs it actually locks. Define what I
believe is the correct behaviour and gets rid of the lock dep ordering
warning.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_ring.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ring.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 168a555d6fba..747b4bffb84b 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
@@ -56,10 +56,12 @@ int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib) | |||
56 | set_bit(i, rdev->ib_pool.alloc_bm); | 56 | set_bit(i, rdev->ib_pool.alloc_bm); |
57 | rdev->ib_pool.ibs[i].length_dw = 0; | 57 | rdev->ib_pool.ibs[i].length_dw = 0; |
58 | *ib = &rdev->ib_pool.ibs[i]; | 58 | *ib = &rdev->ib_pool.ibs[i]; |
59 | mutex_unlock(&rdev->ib_pool.mutex); | ||
59 | goto out; | 60 | goto out; |
60 | } | 61 | } |
61 | if (list_empty(&rdev->ib_pool.scheduled_ibs)) { | 62 | if (list_empty(&rdev->ib_pool.scheduled_ibs)) { |
62 | /* we go do nothings here */ | 63 | /* we go do nothings here */ |
64 | mutex_unlock(&rdev->ib_pool.mutex); | ||
63 | DRM_ERROR("all IB allocated none scheduled.\n"); | 65 | DRM_ERROR("all IB allocated none scheduled.\n"); |
64 | r = -EINVAL; | 66 | r = -EINVAL; |
65 | goto out; | 67 | goto out; |
@@ -69,10 +71,13 @@ int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib) | |||
69 | struct radeon_ib, list); | 71 | struct radeon_ib, list); |
70 | if (nib->fence == NULL) { | 72 | if (nib->fence == NULL) { |
71 | /* we go do nothings here */ | 73 | /* we go do nothings here */ |
74 | mutex_unlock(&rdev->ib_pool.mutex); | ||
72 | DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx); | 75 | DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx); |
73 | r = -EINVAL; | 76 | r = -EINVAL; |
74 | goto out; | 77 | goto out; |
75 | } | 78 | } |
79 | mutex_unlock(&rdev->ib_pool.mutex); | ||
80 | |||
76 | r = radeon_fence_wait(nib->fence, false); | 81 | r = radeon_fence_wait(nib->fence, false); |
77 | if (r) { | 82 | if (r) { |
78 | DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx, | 83 | DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx, |
@@ -81,12 +86,17 @@ int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib) | |||
81 | goto out; | 86 | goto out; |
82 | } | 87 | } |
83 | radeon_fence_unref(&nib->fence); | 88 | radeon_fence_unref(&nib->fence); |
89 | |||
84 | nib->length_dw = 0; | 90 | nib->length_dw = 0; |
91 | |||
92 | /* scheduled list is accessed here */ | ||
93 | mutex_lock(&rdev->ib_pool.mutex); | ||
85 | list_del(&nib->list); | 94 | list_del(&nib->list); |
86 | INIT_LIST_HEAD(&nib->list); | 95 | INIT_LIST_HEAD(&nib->list); |
96 | mutex_unlock(&rdev->ib_pool.mutex); | ||
97 | |||
87 | *ib = nib; | 98 | *ib = nib; |
88 | out: | 99 | out: |
89 | mutex_unlock(&rdev->ib_pool.mutex); | ||
90 | if (r) { | 100 | if (r) { |
91 | radeon_fence_unref(&fence); | 101 | radeon_fence_unref(&fence); |
92 | } else { | 102 | } else { |
@@ -110,9 +120,10 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) | |||
110 | return; | 120 | return; |
111 | } | 121 | } |
112 | list_del(&tmp->list); | 122 | list_del(&tmp->list); |
113 | if (tmp->fence) { | 123 | INIT_LIST_HEAD(&tmp->list); |
124 | if (tmp->fence) | ||
114 | radeon_fence_unref(&tmp->fence); | 125 | radeon_fence_unref(&tmp->fence); |
115 | } | 126 | |
116 | tmp->length_dw = 0; | 127 | tmp->length_dw = 0; |
117 | clear_bit(tmp->idx, rdev->ib_pool.alloc_bm); | 128 | clear_bit(tmp->idx, rdev->ib_pool.alloc_bm); |
118 | mutex_unlock(&rdev->ib_pool.mutex); | 129 | mutex_unlock(&rdev->ib_pool.mutex); |
@@ -122,25 +133,24 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) | |||
122 | { | 133 | { |
123 | int r = 0; | 134 | int r = 0; |
124 | 135 | ||
125 | mutex_lock(&rdev->ib_pool.mutex); | ||
126 | if (!ib->length_dw || !rdev->cp.ready) { | 136 | if (!ib->length_dw || !rdev->cp.ready) { |
127 | /* TODO: Nothings in the ib we should report. */ | 137 | /* TODO: Nothings in the ib we should report. */ |
128 | mutex_unlock(&rdev->ib_pool.mutex); | ||
129 | DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx); | 138 | DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx); |
130 | return -EINVAL; | 139 | return -EINVAL; |
131 | } | 140 | } |
141 | |||
132 | /* 64 dwords should be enough for fence too */ | 142 | /* 64 dwords should be enough for fence too */ |
133 | r = radeon_ring_lock(rdev, 64); | 143 | r = radeon_ring_lock(rdev, 64); |
134 | if (r) { | 144 | if (r) { |
135 | DRM_ERROR("radeon: scheduling IB failled (%d).\n", r); | 145 | DRM_ERROR("radeon: scheduling IB failled (%d).\n", r); |
136 | mutex_unlock(&rdev->ib_pool.mutex); | ||
137 | return r; | 146 | return r; |
138 | } | 147 | } |
139 | radeon_ring_ib_execute(rdev, ib); | 148 | radeon_ring_ib_execute(rdev, ib); |
140 | radeon_fence_emit(rdev, ib->fence); | 149 | radeon_fence_emit(rdev, ib->fence); |
141 | radeon_ring_unlock_commit(rdev); | 150 | mutex_lock(&rdev->ib_pool.mutex); |
142 | list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs); | 151 | list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs); |
143 | mutex_unlock(&rdev->ib_pool.mutex); | 152 | mutex_unlock(&rdev->ib_pool.mutex); |
153 | radeon_ring_unlock_commit(rdev); | ||
144 | return 0; | 154 | return 0; |
145 | } | 155 | } |
146 | 156 | ||