aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/cdma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/host1x/cdma.c')
-rw-r--r--drivers/gpu/host1x/cdma.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/drivers/gpu/host1x/cdma.c b/drivers/gpu/host1x/cdma.c
index a18db4d5347c..c5d82a8a2ec9 100644
--- a/drivers/gpu/host1x/cdma.c
+++ b/drivers/gpu/host1x/cdma.c
@@ -96,12 +96,12 @@ fail:
96 */ 96 */
97static void host1x_pushbuffer_push(struct push_buffer *pb, u32 op1, u32 op2) 97static void host1x_pushbuffer_push(struct push_buffer *pb, u32 op1, u32 op2)
98{ 98{
99 u32 pos = pb->pos; 99 u32 *p = (u32 *)((void *)pb->mapped + pb->pos);
100 u32 *p = (u32 *)((void *)pb->mapped + pos); 100
101 WARN_ON(pos == pb->fence); 101 WARN_ON(pb->pos == pb->fence);
102 *(p++) = op1; 102 *(p++) = op1;
103 *(p++) = op2; 103 *(p++) = op2;
104 pb->pos = (pos + 8) & (pb->size_bytes - 1); 104 pb->pos = (pb->pos + 8) & (pb->size_bytes - 1);
105} 105}
106 106
107/* 107/*
@@ -134,14 +134,19 @@ unsigned int host1x_cdma_wait_locked(struct host1x_cdma *cdma,
134 enum cdma_event event) 134 enum cdma_event event)
135{ 135{
136 for (;;) { 136 for (;;) {
137 struct push_buffer *pb = &cdma->push_buffer;
137 unsigned int space; 138 unsigned int space;
138 139
139 if (event == CDMA_EVENT_SYNC_QUEUE_EMPTY) 140 switch (event) {
141 case CDMA_EVENT_SYNC_QUEUE_EMPTY:
140 space = list_empty(&cdma->sync_queue) ? 1 : 0; 142 space = list_empty(&cdma->sync_queue) ? 1 : 0;
141 else if (event == CDMA_EVENT_PUSH_BUFFER_SPACE) { 143 break;
142 struct push_buffer *pb = &cdma->push_buffer; 144
145 case CDMA_EVENT_PUSH_BUFFER_SPACE:
143 space = host1x_pushbuffer_space(pb); 146 space = host1x_pushbuffer_space(pb);
144 } else { 147 break;
148
149 default:
145 WARN_ON(1); 150 WARN_ON(1);
146 return -EINVAL; 151 return -EINVAL;
147 } 152 }
@@ -159,12 +164,14 @@ unsigned int host1x_cdma_wait_locked(struct host1x_cdma *cdma,
159 mutex_lock(&cdma->lock); 164 mutex_lock(&cdma->lock);
160 continue; 165 continue;
161 } 166 }
167
162 cdma->event = event; 168 cdma->event = event;
163 169
164 mutex_unlock(&cdma->lock); 170 mutex_unlock(&cdma->lock);
165 down(&cdma->sem); 171 down(&cdma->sem);
166 mutex_lock(&cdma->lock); 172 mutex_lock(&cdma->lock);
167 } 173 }
174
168 return 0; 175 return 0;
169} 176}
170 177
@@ -234,6 +241,7 @@ static void update_cdma_locked(struct host1x_cdma *cdma)
234 /* Start timer on next pending syncpt */ 241 /* Start timer on next pending syncpt */
235 if (job->timeout) 242 if (job->timeout)
236 cdma_start_timer_locked(cdma, job); 243 cdma_start_timer_locked(cdma, job);
244
237 break; 245 break;
238 } 246 }
239 247
@@ -247,7 +255,9 @@ static void update_cdma_locked(struct host1x_cdma *cdma)
247 /* Pop push buffer slots */ 255 /* Pop push buffer slots */
248 if (job->num_slots) { 256 if (job->num_slots) {
249 struct push_buffer *pb = &cdma->push_buffer; 257 struct push_buffer *pb = &cdma->push_buffer;
258
250 host1x_pushbuffer_pop(pb, job->num_slots); 259 host1x_pushbuffer_pop(pb, job->num_slots);
260
251 if (cdma->event == CDMA_EVENT_PUSH_BUFFER_SPACE) 261 if (cdma->event == CDMA_EVENT_PUSH_BUFFER_SPACE)
252 signal = true; 262 signal = true;
253 } 263 }
@@ -269,11 +279,9 @@ static void update_cdma_locked(struct host1x_cdma *cdma)
269void host1x_cdma_update_sync_queue(struct host1x_cdma *cdma, 279void host1x_cdma_update_sync_queue(struct host1x_cdma *cdma,
270 struct device *dev) 280 struct device *dev)
271{ 281{
272 u32 restart_addr;
273 u32 syncpt_incrs;
274 struct host1x_job *job = NULL;
275 u32 syncpt_val;
276 struct host1x *host1x = cdma_to_host1x(cdma); 282 struct host1x *host1x = cdma_to_host1x(cdma);
283 u32 restart_addr, syncpt_incrs, syncpt_val;
284 struct host1x_job *job = NULL;
277 285
278 syncpt_val = host1x_syncpt_load(cdma->timeout.syncpt); 286 syncpt_val = host1x_syncpt_load(cdma->timeout.syncpt);
279 287
@@ -342,9 +350,11 @@ void host1x_cdma_update_sync_queue(struct host1x_cdma *cdma,
342 syncpt_val += syncpt_incrs; 350 syncpt_val += syncpt_incrs;
343 } 351 }
344 352
345 /* The following sumbits from the same client may be dependent on the 353 /*
354 * The following sumbits from the same client may be dependent on the
346 * failed submit and therefore they may fail. Force a small timeout 355 * failed submit and therefore they may fail. Force a small timeout
347 * to make the queue cleanup faster */ 356 * to make the queue cleanup faster.
357 */
348 358
349 list_for_each_entry_from(job, &cdma->sync_queue, list) 359 list_for_each_entry_from(job, &cdma->sync_queue, list)
350 if (job->client == cdma->timeout.client) 360 if (job->client == cdma->timeout.client)
@@ -375,6 +385,7 @@ int host1x_cdma_init(struct host1x_cdma *cdma)
375 err = host1x_pushbuffer_init(&cdma->push_buffer); 385 err = host1x_pushbuffer_init(&cdma->push_buffer);
376 if (err) 386 if (err)
377 return err; 387 return err;
388
378 return 0; 389 return 0;
379} 390}
380 391
@@ -410,6 +421,7 @@ int host1x_cdma_begin(struct host1x_cdma *cdma, struct host1x_job *job)
410 /* init state on first submit with timeout value */ 421 /* init state on first submit with timeout value */
411 if (!cdma->timeout.initialized) { 422 if (!cdma->timeout.initialized) {
412 int err; 423 int err;
424
413 err = host1x_hw_cdma_timeout_init(host1x, cdma, 425 err = host1x_hw_cdma_timeout_init(host1x, cdma,
414 job->syncpt_id); 426 job->syncpt_id);
415 if (err) { 427 if (err) {
@@ -418,6 +430,7 @@ int host1x_cdma_begin(struct host1x_cdma *cdma, struct host1x_job *job)
418 } 430 }
419 } 431 }
420 } 432 }
433
421 if (!cdma->running) 434 if (!cdma->running)
422 host1x_hw_cdma_start(host1x, cdma); 435 host1x_hw_cdma_start(host1x, cdma);
423 436
@@ -448,6 +461,7 @@ void host1x_cdma_push(struct host1x_cdma *cdma, u32 op1, u32 op2)
448 slots_free = host1x_cdma_wait_locked(cdma, 461 slots_free = host1x_cdma_wait_locked(cdma,
449 CDMA_EVENT_PUSH_BUFFER_SPACE); 462 CDMA_EVENT_PUSH_BUFFER_SPACE);
450 } 463 }
464
451 cdma->slots_free = slots_free - 1; 465 cdma->slots_free = slots_free - 1;
452 cdma->slots_used++; 466 cdma->slots_used++;
453 host1x_pushbuffer_push(pb, op1, op2); 467 host1x_pushbuffer_push(pb, op1, op2);