aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Paul <seanpaul@chromium.org>2018-02-28 14:19:01 -0500
committerRob Clark <robdclark@gmail.com>2018-06-04 12:50:31 -0400
commit70db18dca4e0130acb0600ad51c33176b6162ccc (patch)
tree167594fdb755bd979e0359e206a9833060a1b376
parente765ea77b0fd51152e07aa4e6850b81552b76da3 (diff)
drm/msm: Remove msm_commit/worker, use atomic helper commit
Moving further towards switching fully to the the atomic helpers, this patch removes the hand-rolled worker nonblock commit code and uses the atomic helpers commit_work model. Changes in v2: - Remove commit_destroy() - Shuffle order of commit_tail calls to further serialize commits - Use stall in swap_state to avoid abandoned events on disable Changes in v3: - Rebased on Archit's private_obj set Changes in v4: - None Signed-off-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c153
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c1
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h4
3 files changed, 42 insertions, 116 deletions
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 94f9c3e0e7bf..95c7868445dd 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -21,66 +21,6 @@
21#include "msm_gem.h" 21#include "msm_gem.h"
22#include "msm_fence.h" 22#include "msm_fence.h"
23 23
24struct msm_commit {
25 struct drm_device *dev;
26 struct drm_atomic_state *state;
27 struct work_struct work;
28 uint32_t crtc_mask;
29};
30
31static void commit_worker(struct work_struct *work);
32
33/* block until specified crtcs are no longer pending update, and
34 * atomically mark them as pending update
35 */
36static int start_atomic(struct msm_drm_private *priv, uint32_t crtc_mask)
37{
38 int ret;
39
40 spin_lock(&priv->pending_crtcs_event.lock);
41 ret = wait_event_interruptible_locked(priv->pending_crtcs_event,
42 !(priv->pending_crtcs & crtc_mask));
43 if (ret == 0) {
44 DBG("start: %08x", crtc_mask);
45 priv->pending_crtcs |= crtc_mask;
46 }
47 spin_unlock(&priv->pending_crtcs_event.lock);
48
49 return ret;
50}
51
52/* clear specified crtcs (no longer pending update)
53 */
54static void end_atomic(struct msm_drm_private *priv, uint32_t crtc_mask)
55{
56 spin_lock(&priv->pending_crtcs_event.lock);
57 DBG("end: %08x", crtc_mask);
58 priv->pending_crtcs &= ~crtc_mask;
59 wake_up_all_locked(&priv->pending_crtcs_event);
60 spin_unlock(&priv->pending_crtcs_event.lock);
61}
62
63static struct msm_commit *commit_init(struct drm_atomic_state *state)
64{
65 struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
66
67 if (!c)
68 return NULL;
69
70 c->dev = state->dev;
71 c->state = state;
72
73 INIT_WORK(&c->work, commit_worker);
74
75 return c;
76}
77
78static void commit_destroy(struct msm_commit *c)
79{
80 end_atomic(c->dev->dev_private, c->crtc_mask);
81 kfree(c);
82}
83
84static void msm_atomic_wait_for_commit_done(struct drm_device *dev, 24static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
85 struct drm_atomic_state *old_state) 25 struct drm_atomic_state *old_state)
86{ 26{
@@ -148,31 +88,37 @@ static void msm_atomic_commit_tail(struct drm_atomic_state *state)
148 88
149 msm_atomic_wait_for_commit_done(dev, state); 89 msm_atomic_wait_for_commit_done(dev, state);
150 90
151 drm_atomic_helper_cleanup_planes(dev, state);
152
153 kms->funcs->complete_commit(kms, state); 91 kms->funcs->complete_commit(kms, state);
92
93 drm_atomic_helper_wait_for_vblanks(dev, state);
94
95 drm_atomic_helper_commit_hw_done(state);
96
97 drm_atomic_helper_cleanup_planes(dev, state);
154} 98}
155 99
156/* The (potentially) asynchronous part of the commit. At this point 100/* The (potentially) asynchronous part of the commit. At this point
157 * nothing can fail short of armageddon. 101 * nothing can fail short of armageddon.
158 */ 102 */
159static void complete_commit(struct msm_commit *c) 103static void commit_tail(struct drm_atomic_state *state)
160{ 104{
161 struct drm_atomic_state *state = c->state; 105 drm_atomic_helper_wait_for_fences(state->dev, state, false);
162 struct drm_device *dev = state->dev;
163 106
164 drm_atomic_helper_wait_for_fences(dev, state, false); 107 drm_atomic_helper_wait_for_dependencies(state);
165 108
166 msm_atomic_commit_tail(state); 109 msm_atomic_commit_tail(state);
167 110
168 drm_atomic_state_put(state); 111 drm_atomic_helper_commit_cleanup_done(state);
169 112
170 commit_destroy(c); 113 drm_atomic_state_put(state);
171} 114}
172 115
173static void commit_worker(struct work_struct *work) 116static void commit_work(struct work_struct *work)
174{ 117{
175 complete_commit(container_of(work, struct msm_commit, work)); 118 struct drm_atomic_state *state = container_of(work,
119 struct drm_atomic_state,
120 commit_work);
121 commit_tail(state);
176} 122}
177 123
178/** 124/**
@@ -191,17 +137,12 @@ int msm_atomic_commit(struct drm_device *dev,
191 struct drm_atomic_state *state, bool nonblock) 137 struct drm_atomic_state *state, bool nonblock)
192{ 138{
193 struct msm_drm_private *priv = dev->dev_private; 139 struct msm_drm_private *priv = dev->dev_private;
194 struct msm_commit *c;
195 struct drm_crtc *crtc; 140 struct drm_crtc *crtc;
196 struct drm_crtc_state *crtc_state; 141 struct drm_crtc_state *crtc_state;
197 struct drm_plane *plane; 142 struct drm_plane *plane;
198 struct drm_plane_state *old_plane_state, *new_plane_state; 143 struct drm_plane_state *old_plane_state, *new_plane_state;
199 int i, ret; 144 int i, ret;
200 145
201 ret = drm_atomic_helper_prepare_planes(dev, state);
202 if (ret)
203 return ret;
204
205 /* 146 /*
206 * Note that plane->atomic_async_check() should fail if we need 147 * Note that plane->atomic_async_check() should fail if we need
207 * to re-assign hwpipe or anything that touches global atomic 148 * to re-assign hwpipe or anything that touches global atomic
@@ -209,45 +150,39 @@ int msm_atomic_commit(struct drm_device *dev,
209 * cases. 150 * cases.
210 */ 151 */
211 if (state->async_update) { 152 if (state->async_update) {
153 ret = drm_atomic_helper_prepare_planes(dev, state);
154 if (ret)
155 return ret;
156
212 drm_atomic_helper_async_commit(dev, state); 157 drm_atomic_helper_async_commit(dev, state);
213 drm_atomic_helper_cleanup_planes(dev, state); 158 drm_atomic_helper_cleanup_planes(dev, state);
214 return 0; 159 return 0;
215 } 160 }
216 161
217 c = commit_init(state); 162 ret = drm_atomic_helper_setup_commit(state, nonblock);
218 if (!c) { 163 if (ret)
219 ret = -ENOMEM; 164 return ret;
220 goto error;
221 }
222 165
223 /* 166 INIT_WORK(&state->commit_work, commit_work);
224 * Figure out what crtcs we have:
225 */
226 for_each_new_crtc_in_state(state, crtc, crtc_state, i)
227 c->crtc_mask |= drm_crtc_mask(crtc);
228 167
229 /* 168 ret = drm_atomic_helper_prepare_planes(dev, state);
230 * Figure out what fence to wait for: 169 if (ret)
231 */ 170 return ret;
232 for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { 171
233 if ((new_plane_state->fb != old_plane_state->fb) && new_plane_state->fb) { 172 if (!nonblock) {
234 struct drm_gem_object *obj = msm_framebuffer_bo(new_plane_state->fb, 0); 173 ret = drm_atomic_helper_wait_for_fences(dev, state, true);
235 struct msm_gem_object *msm_obj = to_msm_bo(obj); 174 if (ret)
236 struct dma_fence *fence = reservation_object_get_excl_rcu(msm_obj->resv); 175 goto error;
237
238 drm_atomic_set_fence_for_plane(new_plane_state, fence);
239 }
240 } 176 }
241 177
242 /* 178 /*
243 * Wait for pending updates on any of the same crtc's and then 179 * This is the point of no return - everything below never fails except
244 * mark our set of crtc's as busy: 180 * when the hw goes bonghits. Which means we can commit the new state on
181 * the software side now.
182 *
183 * swap driver private state while still holding state_lock
245 */ 184 */
246 ret = start_atomic(dev->dev_private, c->crtc_mask); 185 BUG_ON(drm_atomic_helper_swap_state(state, true) < 0);
247 if (ret)
248 goto err_free;
249
250 BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
251 186
252 /* 187 /*
253 * This is the point of no return - everything below never fails except 188 * This is the point of no return - everything below never fails except
@@ -272,17 +207,13 @@ int msm_atomic_commit(struct drm_device *dev,
272 */ 207 */
273 208
274 drm_atomic_state_get(state); 209 drm_atomic_state_get(state);
275 if (nonblock) { 210 if (nonblock)
276 queue_work(priv->atomic_wq, &c->work); 211 queue_work(system_unbound_wq, &state->commit_work);
277 return 0; 212 else
278 } 213 commit_tail(state);
279
280 complete_commit(c);
281 214
282 return 0; 215 return 0;
283 216
284err_free:
285 kfree(c);
286error: 217error:
287 drm_atomic_helper_cleanup_planes(dev, state); 218 drm_atomic_helper_cleanup_planes(dev, state);
288 return ret; 219 return ret;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 1c89195da4ff..9cec74c79aa2 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -381,7 +381,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
381 381
382 priv->wq = alloc_ordered_workqueue("msm", 0); 382 priv->wq = alloc_ordered_workqueue("msm", 0);
383 priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0); 383 priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0);
384 init_waitqueue_head(&priv->pending_crtcs_event);
385 384
386 INIT_LIST_HEAD(&priv->inactive_list); 385 INIT_LIST_HEAD(&priv->inactive_list);
387 INIT_LIST_HEAD(&priv->vblank_ctrl.event_list); 386 INIT_LIST_HEAD(&priv->vblank_ctrl.event_list);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 98e82230b904..2b2688896295 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -117,10 +117,6 @@ struct msm_drm_private {
117 struct workqueue_struct *wq; 117 struct workqueue_struct *wq;
118 struct workqueue_struct *atomic_wq; 118 struct workqueue_struct *atomic_wq;
119 119
120 /* crtcs pending async atomic updates: */
121 uint32_t pending_crtcs;
122 wait_queue_head_t pending_crtcs_event;
123
124 unsigned int num_planes; 120 unsigned int num_planes;
125 struct drm_plane *planes[16]; 121 struct drm_plane *planes[16];
126 122