blob: db913a588b3f59eac3b44f1407322e8d5b70e5fd [file] [log] [blame]
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001/* Copyright (c) 2002,2007-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#include <linux/firmware.h>
14#include <linux/slab.h>
15#include <linux/sched.h>
16#include <linux/log2.h>
17
18#include "kgsl.h"
19#include "kgsl_sharedmem.h"
20#include "kgsl_cffdump.h"
21
22#include "adreno.h"
23#include "adreno_pm4types.h"
24#include "adreno_ringbuffer.h"
25
Jeremy Gebbeneebc4612011-08-31 10:15:21 -070026#include "a2xx_reg.h"
Jordan Crouseb4d31bd2012-02-01 22:11:12 -070027#include "a3xx_reg.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070028
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070029#define GSL_RB_NOP_SIZEDWORDS 2
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070030
Jordan Crouseb4d31bd2012-02-01 22:11:12 -070031void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070032{
33 BUG_ON(rb->wptr == 0);
34
Lucille Sylvester958dc942011-09-06 18:19:49 -060035 /* Let the pwrscale policy know that new commands have
36 been submitted. */
37 kgsl_pwrscale_busy(rb->device);
38
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070039 /*synchronize memory before informing the hardware of the
40 *new commands.
41 */
42 mb();
43
44 adreno_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr);
45}
46
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -070047static int
48adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb,
49 struct adreno_context *context,
50 unsigned int numcmds, int wptr_ahead)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051{
52 int nopcount;
53 unsigned int freecmds;
54 unsigned int *cmds;
55 uint cmds_gpu;
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -060056 unsigned long wait_time;
Jordan Crouse21f75a02012-08-09 15:08:59 -060057 unsigned long wait_timeout = msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
Tarun Karra3335f142012-06-19 14:11:48 -070058 unsigned long wait_time_part;
Tarun Karra3335f142012-06-19 14:11:48 -070059 unsigned int prev_reg_val[hang_detect_regs_count];
60
61 memset(prev_reg_val, 0, sizeof(prev_reg_val));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070062
63 /* if wptr ahead, fill the remaining with NOPs */
64 if (wptr_ahead) {
65 /* -1 for header */
66 nopcount = rb->sizedwords - rb->wptr - 1;
67
68 cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
69 cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*rb->wptr;
70
Jordan Crouse084427d2011-07-28 08:37:58 -060071 GSL_RB_WRITE(cmds, cmds_gpu, cp_nop_packet(nopcount));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070072
73 /* Make sure that rptr is not 0 before submitting
74 * commands at the end of ringbuffer. We do not
75 * want the rptr and wptr to become equal when
76 * the ringbuffer is not empty */
77 do {
78 GSL_RB_GET_READPTR(rb, &rb->rptr);
79 } while (!rb->rptr);
80
81 rb->wptr++;
82
83 adreno_ringbuffer_submit(rb);
84
85 rb->wptr = 0;
86 }
87
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -060088 wait_time = jiffies + wait_timeout;
Jordan Crouse21f75a02012-08-09 15:08:59 -060089 wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070090 /* wait for space in ringbuffer */
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -060091 while (1) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070092 GSL_RB_GET_READPTR(rb, &rb->rptr);
93
94 freecmds = rb->rptr - rb->wptr;
95
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -060096 if (freecmds == 0 || freecmds > numcmds)
97 break;
98
Tarun Karra3335f142012-06-19 14:11:48 -070099 /* Dont wait for timeout, detect hang faster.
100 */
101 if (time_after(jiffies, wait_time_part)) {
102 wait_time_part = jiffies +
Jordan Crouse21f75a02012-08-09 15:08:59 -0600103 msecs_to_jiffies(KGSL_TIMEOUT_PART);
Tarun Karra3335f142012-06-19 14:11:48 -0700104 if ((adreno_hang_detect(rb->device,
105 prev_reg_val))){
106 KGSL_DRV_ERR(rb->device,
107 "Hang detected while waiting for freespace in"
108 "ringbuffer rptr: 0x%x, wptr: 0x%x\n",
109 rb->rptr, rb->wptr);
110 goto err;
111 }
112 }
113
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600114 if (time_after(jiffies, wait_time)) {
115 KGSL_DRV_ERR(rb->device,
116 "Timed out while waiting for freespace in ringbuffer "
117 "rptr: 0x%x, wptr: 0x%x\n", rb->rptr, rb->wptr);
Tarun Karra3335f142012-06-19 14:11:48 -0700118 goto err;
119 }
120
Wei Zou50ec3372012-07-17 15:46:52 -0700121 continue;
122
Tarun Karra3335f142012-06-19 14:11:48 -0700123err:
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700124 if (!adreno_dump_and_recover(rb->device)) {
125 if (context && context->flags & CTXT_FLAGS_GPU_HANG) {
126 KGSL_CTXT_WARN(rb->device,
127 "Context %p caused a gpu hang. Will not accept commands for context %d\n",
128 context, context->id);
129 return -EDEADLK;
130 }
131 wait_time = jiffies + wait_timeout;
132 } else {
133 /* GPU is hung and we cannot recover */
134 BUG();
135 }
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600136 }
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700137 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700138}
139
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700140unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700141 struct adreno_context *context,
142 unsigned int numcmds)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700143{
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700144 unsigned int *ptr = NULL;
145 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700146 BUG_ON(numcmds >= rb->sizedwords);
147
148 GSL_RB_GET_READPTR(rb, &rb->rptr);
149 /* check for available space */
150 if (rb->wptr >= rb->rptr) {
151 /* wptr ahead or equal to rptr */
152 /* reserve dwords for nop packet */
153 if ((rb->wptr + numcmds) > (rb->sizedwords -
154 GSL_RB_NOP_SIZEDWORDS))
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700155 ret = adreno_ringbuffer_waitspace(rb, context,
156 numcmds, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700157 } else {
158 /* wptr behind rptr */
159 if ((rb->wptr + numcmds) >= rb->rptr)
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700160 ret = adreno_ringbuffer_waitspace(rb, context,
161 numcmds, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700162 /* check for remaining space */
163 /* reserve dwords for nop packet */
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700164 if (!ret && (rb->wptr + numcmds) > (rb->sizedwords -
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165 GSL_RB_NOP_SIZEDWORDS))
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700166 ret = adreno_ringbuffer_waitspace(rb, context,
167 numcmds, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700168 }
169
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700170 if (!ret) {
171 ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
172 rb->wptr += numcmds;
173 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700174
175 return ptr;
176}
177
178static int _load_firmware(struct kgsl_device *device, const char *fwfile,
179 void **data, int *len)
180{
181 const struct firmware *fw = NULL;
182 int ret;
183
184 ret = request_firmware(&fw, fwfile, device->dev);
185
186 if (ret) {
187 KGSL_DRV_ERR(device, "request_firmware(%s) failed: %d\n",
188 fwfile, ret);
189 return ret;
190 }
191
192 *data = kmalloc(fw->size, GFP_KERNEL);
193
194 if (*data) {
195 memcpy(*data, fw->data, fw->size);
196 *len = fw->size;
197 } else
198 KGSL_MEM_ERR(device, "kmalloc(%d) failed\n", fw->size);
199
200 release_firmware(fw);
201 return (*data != NULL) ? 0 : -ENOMEM;
202}
203
204static int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device)
205{
206 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207 int i, ret = 0;
208
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700209 if (adreno_dev->pm4_fw == NULL) {
210 int len;
Jordan Crouse505df9c2011-07-28 08:37:59 -0600211 void *ptr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700212
Jordan Crouse505df9c2011-07-28 08:37:59 -0600213 ret = _load_firmware(device, adreno_dev->pm4_fwfile,
214 &ptr, &len);
215
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700216 if (ret)
217 goto err;
218
219 /* PM4 size is 3 dword aligned plus 1 dword of version */
220 if (len % ((sizeof(uint32_t) * 3)) != sizeof(uint32_t)) {
221 KGSL_DRV_ERR(device, "Bad firmware size: %d\n", len);
222 ret = -EINVAL;
Jeremy Gebben79acee62011-08-08 16:44:07 -0600223 kfree(ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700224 goto err;
225 }
226
227 adreno_dev->pm4_fw_size = len / sizeof(uint32_t);
228 adreno_dev->pm4_fw = ptr;
229 }
230
231 KGSL_DRV_INFO(device, "loading pm4 ucode version: %d\n",
232 adreno_dev->pm4_fw[0]);
233
234 adreno_regwrite(device, REG_CP_DEBUG, 0x02000000);
235 adreno_regwrite(device, REG_CP_ME_RAM_WADDR, 0);
236 for (i = 1; i < adreno_dev->pm4_fw_size; i++)
237 adreno_regwrite(device, REG_CP_ME_RAM_DATA,
238 adreno_dev->pm4_fw[i]);
239err:
240 return ret;
241}
242
243static int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device)
244{
245 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700246 int i, ret = 0;
247
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700248 if (adreno_dev->pfp_fw == NULL) {
249 int len;
Jordan Crouse505df9c2011-07-28 08:37:59 -0600250 void *ptr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700251
Jordan Crouse505df9c2011-07-28 08:37:59 -0600252 ret = _load_firmware(device, adreno_dev->pfp_fwfile,
253 &ptr, &len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700254 if (ret)
255 goto err;
256
257 /* PFP size shold be dword aligned */
258 if (len % sizeof(uint32_t) != 0) {
259 KGSL_DRV_ERR(device, "Bad firmware size: %d\n", len);
260 ret = -EINVAL;
Jeremy Gebben79acee62011-08-08 16:44:07 -0600261 kfree(ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700262 goto err;
263 }
264
265 adreno_dev->pfp_fw_size = len / sizeof(uint32_t);
266 adreno_dev->pfp_fw = ptr;
267 }
268
269 KGSL_DRV_INFO(device, "loading pfp ucode version: %d\n",
270 adreno_dev->pfp_fw[0]);
271
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700272 adreno_regwrite(device, adreno_dev->gpudev->reg_cp_pfp_ucode_addr, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700273 for (i = 1; i < adreno_dev->pfp_fw_size; i++)
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700274 adreno_regwrite(device,
275 adreno_dev->gpudev->reg_cp_pfp_ucode_data,
276 adreno_dev->pfp_fw[i]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700277err:
278 return ret;
279}
280
281int adreno_ringbuffer_start(struct adreno_ringbuffer *rb, unsigned int init_ram)
282{
283 int status;
284 /*cp_rb_cntl_u cp_rb_cntl; */
285 union reg_cp_rb_cntl cp_rb_cntl;
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700286 unsigned int rb_cntl;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700287 struct kgsl_device *device = rb->device;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700288 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700289
290 if (rb->flags & KGSL_FLAGS_STARTED)
291 return 0;
292
Carter Coopercb3e8eb2012-04-11 09:39:40 -0600293 if (init_ram)
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700294 rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700295
296 kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0,
297 sizeof(struct kgsl_rbmemptrs));
298
299 kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA,
300 (rb->sizedwords << 2));
301
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700302 if (adreno_is_a2xx(adreno_dev)) {
303 adreno_regwrite(device, REG_CP_RB_WPTR_BASE,
304 (rb->memptrs_desc.gpuaddr
305 + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700306
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700307 /* setup WPTR delay */
308 adreno_regwrite(device, REG_CP_RB_WPTR_DELAY,
309 0 /*0x70000010 */);
310 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700311
312 /*setup REG_CP_RB_CNTL */
313 adreno_regread(device, REG_CP_RB_CNTL, &rb_cntl);
314 cp_rb_cntl.val = rb_cntl;
315
316 /*
317 * The size of the ringbuffer in the hardware is the log2
318 * representation of the size in quadwords (sizedwords / 2)
319 */
320 cp_rb_cntl.f.rb_bufsz = ilog2(rb->sizedwords >> 1);
321
322 /*
323 * Specify the quadwords to read before updating mem RPTR.
324 * Like above, pass the log2 representation of the blocksize
325 * in quadwords.
326 */
327 cp_rb_cntl.f.rb_blksz = ilog2(KGSL_RB_BLKSIZE >> 3);
328
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700329 if (adreno_is_a2xx(adreno_dev)) {
330 /* WPTR polling */
331 cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN;
332 }
333
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334 /* mem RPTR writebacks */
335 cp_rb_cntl.f.rb_no_update = GSL_RB_CNTL_NO_UPDATE;
336
337 adreno_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val);
338
339 adreno_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr);
340
341 adreno_regwrite(device, REG_CP_RB_RPTR_ADDR,
342 rb->memptrs_desc.gpuaddr +
343 GSL_RB_MEMPTRS_RPTR_OFFSET);
344
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700345 if (adreno_is_a3xx(adreno_dev)) {
346 /* enable access protection to privileged registers */
347 adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
348
349 /* RBBM registers */
350 adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
351 adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
352 adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
353 adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
354 adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
355 adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);
356
357 /* CP registers */
358 adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
359 adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
360 adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
361 adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
362 adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);
363
364 /* RB registers */
365 adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);
366
367 /* VBIF registers */
368 adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
369 }
370
371 if (adreno_is_a2xx(adreno_dev)) {
372 /* explicitly clear all cp interrupts */
373 adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
374 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700375
376 /* setup scratch/timestamp */
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700377 adreno_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr +
378 KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
379 soptimestamp));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700380
381 adreno_regwrite(device, REG_SCRATCH_UMSK,
382 GSL_RB_MEMPTRS_SCRATCH_MASK);
383
384 /* load the CP ucode */
385
386 status = adreno_ringbuffer_load_pm4_ucode(device);
387 if (status != 0)
388 return status;
389
390 /* load the prefetch parser ucode */
391 status = adreno_ringbuffer_load_pfp_ucode(device);
392 if (status != 0)
393 return status;
394
Kevin Matlageff806df2012-05-07 18:13:21 -0600395 /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
Kevin Matlagee8d35862012-04-26 12:58:15 -0600396 if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev))
Kevin Matlageff806df2012-05-07 18:13:21 -0600397 adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700398
399 rb->rptr = 0;
400 rb->wptr = 0;
401
402 /* clear ME_HALT to start micro engine */
403 adreno_regwrite(device, REG_CP_ME_CNTL, 0);
404
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700405 /* ME init is GPU specific, so jump into the sub-function */
406 adreno_dev->gpudev->rb_init(adreno_dev, rb);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700407
408 /* idle device to validate ME INIT */
Jordan Crousea29a2e02012-08-14 09:09:23 -0600409 status = adreno_idle(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700410
411 if (status == 0)
412 rb->flags |= KGSL_FLAGS_STARTED;
413
414 return status;
415}
416
Carter Cooper6dd94c82011-10-13 14:43:53 -0600417void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700418{
Rajeev Kulkarnibf7a3822012-08-14 21:21:14 +0530419 struct kgsl_device *device = rb->device;
420 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
421
422 if (rb->flags & KGSL_FLAGS_STARTED) {
423 if (adreno_is_a200(adreno_dev))
424 adreno_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000);
425
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700426 rb->flags &= ~KGSL_FLAGS_STARTED;
Rajeev Kulkarnibf7a3822012-08-14 21:21:14 +0530427 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700428}
429
430int adreno_ringbuffer_init(struct kgsl_device *device)
431{
432 int status;
433 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
434 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
435
436 rb->device = device;
437 /*
438 * It is silly to convert this to words and then back to bytes
439 * immediately below, but most of the rest of the code deals
440 * in words, so we might as well only do the math once
441 */
442 rb->sizedwords = KGSL_RB_SIZE >> 2;
443
444 /* allocate memory for ringbuffer */
445 status = kgsl_allocate_contiguous(&rb->buffer_desc,
446 (rb->sizedwords << 2));
447
448 if (status != 0) {
449 adreno_ringbuffer_close(rb);
450 return status;
451 }
452
453 /* allocate memory for polling and timestamps */
454 /* This really can be at 4 byte alignment boundry but for using MMU
455 * we need to make it at page boundary */
456 status = kgsl_allocate_contiguous(&rb->memptrs_desc,
457 sizeof(struct kgsl_rbmemptrs));
458
459 if (status != 0) {
460 adreno_ringbuffer_close(rb);
461 return status;
462 }
463
464 /* overlay structure on memptrs memory */
465 rb->memptrs = (struct kgsl_rbmemptrs *) rb->memptrs_desc.hostptr;
466
467 return 0;
468}
469
Carter Cooper6dd94c82011-10-13 14:43:53 -0600470void adreno_ringbuffer_close(struct adreno_ringbuffer *rb)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700471{
472 struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
473
474 kgsl_sharedmem_free(&rb->buffer_desc);
475 kgsl_sharedmem_free(&rb->memptrs_desc);
476
477 kfree(adreno_dev->pfp_fw);
478 kfree(adreno_dev->pm4_fw);
479
480 adreno_dev->pfp_fw = NULL;
481 adreno_dev->pm4_fw = NULL;
482
483 memset(rb, 0, sizeof(struct adreno_ringbuffer));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700484}
485
486static uint32_t
487adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700488 struct adreno_context *context,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700489 unsigned int flags, unsigned int *cmds,
490 int sizedwords)
491{
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700492 struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700493 unsigned int *ringcmds;
494 unsigned int timestamp;
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700495 unsigned int total_sizedwords = sizedwords;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700496 unsigned int i;
497 unsigned int rcmd_gpu;
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700498 unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
499 unsigned int gpuaddr = rb->device->memstore.gpuaddr;
500
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600501 /*
502 * if the context was not created with per context timestamp
503 * support, we must use the global timestamp since issueibcmds
504 * will be returning that one.
505 */
506 if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)
507 context_id = context->id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700508
509 /* reserve space to temporarily turn off protected mode
510 * error checking if needed
511 */
512 total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
Shubhraprakash Dasc3ad5802012-05-30 18:10:06 -0600513 /* 2 dwords to store the start of command sequence */
514 total_sizedwords += 2;
Carter Cooper7ffaba62012-05-24 13:59:53 -0600515 total_sizedwords += context ? 7 : 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700516
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700517 if (adreno_is_a3xx(adreno_dev))
518 total_sizedwords += 7;
519
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700520 total_sizedwords += 2; /* scratchpad ts for recovery */
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600521 if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700522 total_sizedwords += 3; /* sop timestamp */
523 total_sizedwords += 4; /* eop timestamp */
Rajesh Kemisettic5699302012-04-21 21:09:05 +0530524 total_sizedwords += 3; /* global timestamp without cache
525 * flush for non-zero context */
526 } else {
527 total_sizedwords += 4; /* global timestamp for recovery*/
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700528 }
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700529
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700530 ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
531 if (!ringcmds) {
532 /*
533 * We could not allocate space in ringbuffer, just return the
534 * last timestamp
535 */
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600536 return rb->timestamp[context_id];
537 }
538
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700539 rcmd_gpu = rb->buffer_desc.gpuaddr
540 + sizeof(uint)*(rb->wptr-total_sizedwords);
541
Shubhraprakash Dasc3ad5802012-05-30 18:10:06 -0600542 GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
543 GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
544
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700545 if (flags & KGSL_CMD_FLAGS_PMODE) {
546 /* disable protected mode error checking */
547 GSL_RB_WRITE(ringcmds, rcmd_gpu,
Jordan Crouse084427d2011-07-28 08:37:58 -0600548 cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700549 GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
550 }
551
552 for (i = 0; i < sizedwords; i++) {
553 GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds);
554 cmds++;
555 }
556
557 if (flags & KGSL_CMD_FLAGS_PMODE) {
558 /* re-enable protected mode error checking */
559 GSL_RB_WRITE(ringcmds, rcmd_gpu,
Jordan Crouse084427d2011-07-28 08:37:58 -0600560 cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700561 GSL_RB_WRITE(ringcmds, rcmd_gpu, 1);
562 }
563
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700564 /* always increment the global timestamp. once. */
565 rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
Carter Cooper7ffaba62012-05-24 13:59:53 -0600566
567 if (context && !(flags & KGSL_CMD_FLAGS_DUMMY_INTR_CMD)) {
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700568 if (context_id == KGSL_MEMSTORE_GLOBAL)
Carter Cooper7ffaba62012-05-24 13:59:53 -0600569 rb->timestamp[context->id] =
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700570 rb->timestamp[KGSL_MEMSTORE_GLOBAL];
571 else
572 rb->timestamp[context_id]++;
573 }
574 timestamp = rb->timestamp[context_id];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700575
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700576 /* scratchpad ts for recovery */
Jordan Crouse084427d2011-07-28 08:37:58 -0600577 GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700578 GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700579
580 if (adreno_is_a3xx(adreno_dev)) {
581 /*
582 * FLush HLSQ lazy updates to make sure there are no
583 * rsources pending for indirect loads after the timestamp
584 */
585
586 GSL_RB_WRITE(ringcmds, rcmd_gpu,
587 cp_type3_packet(CP_EVENT_WRITE, 1));
588 GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); /* HLSQ_FLUSH */
589 GSL_RB_WRITE(ringcmds, rcmd_gpu,
590 cp_type3_packet(CP_WAIT_FOR_IDLE, 1));
591 GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
592 }
593
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600594 if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700595 /* start-of-pipeline timestamp */
596 GSL_RB_WRITE(ringcmds, rcmd_gpu,
597 cp_type3_packet(CP_MEM_WRITE, 2));
598 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
Carter Cooper7ffaba62012-05-24 13:59:53 -0600599 KGSL_MEMSTORE_OFFSET(context_id, soptimestamp)));
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700600 GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
601
602 /* end-of-pipeline timestamp */
603 GSL_RB_WRITE(ringcmds, rcmd_gpu,
604 cp_type3_packet(CP_EVENT_WRITE, 3));
605 GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
606 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
Carter Cooper7ffaba62012-05-24 13:59:53 -0600607 KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp)));
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700608 GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700609
Rajesh Kemisettic5699302012-04-21 21:09:05 +0530610 GSL_RB_WRITE(ringcmds, rcmd_gpu,
611 cp_type3_packet(CP_MEM_WRITE, 2));
612 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
Carter Cooper7ffaba62012-05-24 13:59:53 -0600613 KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
614 eoptimestamp)));
Rajesh Kemisettic5699302012-04-21 21:09:05 +0530615 GSL_RB_WRITE(ringcmds, rcmd_gpu,
616 rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
617 } else {
618 GSL_RB_WRITE(ringcmds, rcmd_gpu,
619 cp_type3_packet(CP_EVENT_WRITE, 3));
620 GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
621 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
Carter Cooper7ffaba62012-05-24 13:59:53 -0600622 KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp)));
623 GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[context_id]);
Rajesh Kemisettic5699302012-04-21 21:09:05 +0530624 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700625
Carter Cooper7ffaba62012-05-24 13:59:53 -0600626 if (context) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700627 /* Conditional execution based on memory values */
628 GSL_RB_WRITE(ringcmds, rcmd_gpu,
Jordan Crouse084427d2011-07-28 08:37:58 -0600629 cp_type3_packet(CP_COND_EXEC, 4));
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700630 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
631 KGSL_MEMSTORE_OFFSET(
632 context_id, ts_cmp_enable)) >> 2);
633 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
634 KGSL_MEMSTORE_OFFSET(
635 context_id, ref_wait_ts)) >> 2);
636 GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700637 /* # of conditional command DWORDs */
638 GSL_RB_WRITE(ringcmds, rcmd_gpu, 2);
639 GSL_RB_WRITE(ringcmds, rcmd_gpu,
Jordan Crouse084427d2011-07-28 08:37:58 -0600640 cp_type3_packet(CP_INTERRUPT, 1));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700641 GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK);
642 }
643
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700644 if (adreno_is_a3xx(adreno_dev)) {
645 /* Dummy set-constant to trigger context rollover */
646 GSL_RB_WRITE(ringcmds, rcmd_gpu,
647 cp_type3_packet(CP_SET_CONSTANT, 2));
648 GSL_RB_WRITE(ringcmds, rcmd_gpu,
649 (0x4<<16)|(A3XX_HLSQ_CL_KERNEL_GROUP_X_REG - 0x2000));
650 GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
651 }
652
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700653 adreno_ringbuffer_submit(rb);
654
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700655 return timestamp;
656}
657
Carter Cooper7ffaba62012-05-24 13:59:53 -0600658void
659adreno_ringbuffer_issuecmds_intr(struct kgsl_device *device,
660 struct kgsl_context *k_ctxt,
661 unsigned int *cmds,
662 int sizedwords)
663{
664 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
665 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
666 struct adreno_context *a_ctxt = NULL;
667
668 if (!k_ctxt)
669 return;
670
671 a_ctxt = k_ctxt->devctxt;
672
673 if (k_ctxt->id == KGSL_CONTEXT_INVALID ||
674 a_ctxt == NULL ||
675 device->state & KGSL_STATE_HUNG)
676 return;
677
678 adreno_ringbuffer_addcmds(rb, a_ctxt, KGSL_CMD_FLAGS_DUMMY_INTR_CMD,
679 cmds, sizedwords);
680}
681
Shubhraprakash Dascb068072012-06-07 17:52:41 -0600682unsigned int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700683adreno_ringbuffer_issuecmds(struct kgsl_device *device,
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600684 struct adreno_context *drawctxt,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700685 unsigned int flags,
686 unsigned int *cmds,
687 int sizedwords)
688{
689 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
690 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
691
692 if (device->state & KGSL_STATE_HUNG)
Shubhraprakash Dascb068072012-06-07 17:52:41 -0600693 return kgsl_readtimestamp(device, KGSL_MEMSTORE_GLOBAL,
694 KGSL_TIMESTAMP_RETIRED);
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600695 return adreno_ringbuffer_addcmds(rb, drawctxt, flags, cmds, sizedwords);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700696}
697
Jeremy Gebbend0ab6ad2012-04-06 11:13:35 -0600698static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
699 int sizedwords);
700
701static bool
702_handle_type3(struct kgsl_device_private *dev_priv, uint *hostaddr)
703{
704 unsigned int opcode = cp_type3_opcode(*hostaddr);
705 switch (opcode) {
706 case CP_INDIRECT_BUFFER_PFD:
707 case CP_INDIRECT_BUFFER_PFE:
708 case CP_COND_INDIRECT_BUFFER_PFE:
709 case CP_COND_INDIRECT_BUFFER_PFD:
710 return _parse_ibs(dev_priv, hostaddr[1], hostaddr[2]);
711 case CP_NOP:
712 case CP_WAIT_FOR_IDLE:
713 case CP_WAIT_REG_MEM:
714 case CP_WAIT_REG_EQ:
715 case CP_WAT_REG_GTE:
716 case CP_WAIT_UNTIL_READ:
717 case CP_WAIT_IB_PFD_COMPLETE:
718 case CP_REG_RMW:
719 case CP_REG_TO_MEM:
720 case CP_MEM_WRITE:
721 case CP_MEM_WRITE_CNTR:
722 case CP_COND_EXEC:
723 case CP_COND_WRITE:
724 case CP_EVENT_WRITE:
725 case CP_EVENT_WRITE_SHD:
726 case CP_EVENT_WRITE_CFL:
727 case CP_EVENT_WRITE_ZPD:
728 case CP_DRAW_INDX:
729 case CP_DRAW_INDX_2:
730 case CP_DRAW_INDX_BIN:
731 case CP_DRAW_INDX_2_BIN:
732 case CP_VIZ_QUERY:
733 case CP_SET_STATE:
734 case CP_SET_CONSTANT:
735 case CP_IM_LOAD:
736 case CP_IM_LOAD_IMMEDIATE:
737 case CP_LOAD_CONSTANT_CONTEXT:
738 case CP_INVALIDATE_STATE:
739 case CP_SET_SHADER_BASES:
740 case CP_SET_BIN_MASK:
741 case CP_SET_BIN_SELECT:
742 case CP_SET_BIN_BASE_OFFSET:
743 case CP_SET_BIN_DATA:
744 case CP_CONTEXT_UPDATE:
745 case CP_INTERRUPT:
746 case CP_IM_STORE:
747 case CP_LOAD_STATE:
748 break;
749 /* these shouldn't come from userspace */
750 case CP_ME_INIT:
751 case CP_SET_PROTECTED_MODE:
752 default:
753 KGSL_CMD_ERR(dev_priv->device, "bad CP opcode %0x\n", opcode);
754 return false;
755 break;
756 }
757
758 return true;
759}
760
761static bool
762_handle_type0(struct kgsl_device_private *dev_priv, uint *hostaddr)
763{
764 unsigned int reg = type0_pkt_offset(*hostaddr);
765 unsigned int cnt = type0_pkt_size(*hostaddr);
766 if (reg < 0x0192 || (reg + cnt) >= 0x8000) {
767 KGSL_CMD_ERR(dev_priv->device, "bad type0 reg: 0x%0x cnt: %d\n",
768 reg, cnt);
769 return false;
770 }
771 return true;
772}
773
774/*
775 * Traverse IBs and dump them to test vector. Detect swap by inspecting
776 * register writes, keeping note of the current state, and dump
777 * framebuffer config to test vector
778 */
779static bool _parse_ibs(struct kgsl_device_private *dev_priv,
780 uint gpuaddr, int sizedwords)
781{
782 static uint level; /* recursion level */
783 bool ret = false;
784 uint *hostaddr, *hoststart;
785 int dwords_left = sizedwords; /* dwords left in the current command
786 buffer */
787 struct kgsl_mem_entry *entry;
788
789 spin_lock(&dev_priv->process_priv->mem_lock);
790 entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
791 gpuaddr, sizedwords * sizeof(uint));
792 spin_unlock(&dev_priv->process_priv->mem_lock);
793 if (entry == NULL) {
794 KGSL_CMD_ERR(dev_priv->device,
795 "no mapping for gpuaddr: 0x%08x\n", gpuaddr);
796 return false;
797 }
798
799 hostaddr = (uint *)kgsl_gpuaddr_to_vaddr(&entry->memdesc, gpuaddr);
800 if (hostaddr == NULL) {
801 KGSL_CMD_ERR(dev_priv->device,
802 "no mapping for gpuaddr: 0x%08x\n", gpuaddr);
803 return false;
804 }
805
806 hoststart = hostaddr;
807
808 level++;
809
810 KGSL_CMD_INFO(dev_priv->device, "ib: gpuaddr:0x%08x, wc:%d, hptr:%p\n",
811 gpuaddr, sizedwords, hostaddr);
812
813 mb();
814 while (dwords_left > 0) {
815 bool cur_ret = true;
816 int count = 0; /* dword count including packet header */
817
818 switch (*hostaddr >> 30) {
819 case 0x0: /* type-0 */
820 count = (*hostaddr >> 16)+2;
821 cur_ret = _handle_type0(dev_priv, hostaddr);
822 break;
823 case 0x1: /* type-1 */
824 count = 2;
825 break;
826 case 0x3: /* type-3 */
827 count = ((*hostaddr >> 16) & 0x3fff) + 2;
828 cur_ret = _handle_type3(dev_priv, hostaddr);
829 break;
830 default:
831 KGSL_CMD_ERR(dev_priv->device, "unexpected type: "
832 "type:%d, word:0x%08x @ 0x%p, gpu:0x%08x\n",
833 *hostaddr >> 30, *hostaddr, hostaddr,
834 gpuaddr+4*(sizedwords-dwords_left));
835 cur_ret = false;
836 count = dwords_left;
837 break;
838 }
839
840 if (!cur_ret) {
841 KGSL_CMD_ERR(dev_priv->device,
842 "bad sub-type: #:%d/%d, v:0x%08x"
843 " @ 0x%p[gb:0x%08x], level:%d\n",
844 sizedwords-dwords_left, sizedwords, *hostaddr,
845 hostaddr, gpuaddr+4*(sizedwords-dwords_left),
846 level);
847
848 if (ADRENO_DEVICE(dev_priv->device)->ib_check_level
849 >= 2)
850 print_hex_dump(KERN_ERR,
851 level == 1 ? "IB1:" : "IB2:",
852 DUMP_PREFIX_OFFSET, 32, 4, hoststart,
853 sizedwords*4, 0);
854 goto done;
855 }
856
857 /* jump to next packet */
858 dwords_left -= count;
859 hostaddr += count;
860 if (dwords_left < 0) {
861 KGSL_CMD_ERR(dev_priv->device,
862 "bad count: c:%d, #:%d/%d, "
863 "v:0x%08x @ 0x%p[gb:0x%08x], level:%d\n",
864 count, sizedwords-(dwords_left+count),
865 sizedwords, *(hostaddr-count), hostaddr-count,
866 gpuaddr+4*(sizedwords-(dwords_left+count)),
867 level);
868 if (ADRENO_DEVICE(dev_priv->device)->ib_check_level
869 >= 2)
870 print_hex_dump(KERN_ERR,
871 level == 1 ? "IB1:" : "IB2:",
872 DUMP_PREFIX_OFFSET, 32, 4, hoststart,
873 sizedwords*4, 0);
874 goto done;
875 }
876 }
877
878 ret = true;
879done:
880 if (!ret)
881 KGSL_DRV_ERR(dev_priv->device,
882 "parsing failed: gpuaddr:0x%08x, "
883 "host:0x%p, wc:%d\n", gpuaddr, hoststart, sizedwords);
884
885 level--;
886
887 return ret;
888}
889
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700890int
891adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv,
892 struct kgsl_context *context,
893 struct kgsl_ibdesc *ibdesc,
894 unsigned int numibs,
895 uint32_t *timestamp,
896 unsigned int flags)
897{
898 struct kgsl_device *device = dev_priv->device;
899 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
900 unsigned int *link;
901 unsigned int *cmds;
902 unsigned int i;
Jeremy Gebben3c127f52011-08-08 17:04:11 -0600903 struct adreno_context *drawctxt;
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700904 unsigned int start_index = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700905
906 if (device->state & KGSL_STATE_HUNG)
907 return -EBUSY;
908 if (!(adreno_dev->ringbuffer.flags & KGSL_FLAGS_STARTED) ||
Jeremy Gebben3c127f52011-08-08 17:04:11 -0600909 context == NULL || ibdesc == 0 || numibs == 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700910 return -EINVAL;
911
Jeremy Gebben3c127f52011-08-08 17:04:11 -0600912 drawctxt = context->devctxt;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700913
914 if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
915 KGSL_CTXT_WARN(device, "Context %p caused a gpu hang.."
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700916 " will not accept commands for context %d\n",
917 drawctxt, drawctxt->id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700918 return -EDEADLK;
919 }
Shubhraprakash Dasd23ff4b2012-04-05 16:55:54 -0600920
921 cmds = link = kzalloc(sizeof(unsigned int) * (numibs * 3 + 4),
922 GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700923 if (!link) {
Shubhraprakash Dasd23ff4b2012-04-05 16:55:54 -0600924 KGSL_CORE_ERR("kzalloc(%d) failed\n",
925 sizeof(unsigned int) * (numibs * 3 + 4));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700926 return -ENOMEM;
927 }
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700928
929 /*When preamble is enabled, the preamble buffer with state restoration
930 commands are stored in the first node of the IB chain. We can skip that
931 if a context switch hasn't occured */
932
933 if (drawctxt->flags & CTXT_FLAGS_PREAMBLE &&
934 adreno_dev->drawctxt_active == drawctxt)
935 start_index = 1;
936
Shubhraprakash Dasd23ff4b2012-04-05 16:55:54 -0600937 if (!start_index) {
938 *cmds++ = cp_nop_packet(1);
939 *cmds++ = KGSL_START_OF_IB_IDENTIFIER;
940 } else {
941 *cmds++ = cp_nop_packet(4);
942 *cmds++ = KGSL_START_OF_IB_IDENTIFIER;
943 *cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
944 *cmds++ = ibdesc[0].gpuaddr;
945 *cmds++ = ibdesc[0].sizedwords;
946 }
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700947 for (i = start_index; i < numibs; i++) {
Jeremy Gebbend0ab6ad2012-04-06 11:13:35 -0600948 if (unlikely(adreno_dev->ib_check_level >= 1 &&
949 !_parse_ibs(dev_priv, ibdesc[i].gpuaddr,
950 ibdesc[i].sizedwords))) {
951 kfree(link);
952 return -EINVAL;
953 }
Jordan Crouse084427d2011-07-28 08:37:58 -0600954 *cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700955 *cmds++ = ibdesc[i].gpuaddr;
956 *cmds++ = ibdesc[i].sizedwords;
957 }
958
Shubhraprakash Dasd23ff4b2012-04-05 16:55:54 -0600959 *cmds++ = cp_nop_packet(1);
960 *cmds++ = KGSL_END_OF_IB_IDENTIFIER;
961
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600962 kgsl_setstate(&device->mmu, context->id,
Shubhraprakash Das767fdda2011-08-15 15:49:45 -0600963 kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700964 device->id));
965
966 adreno_drawctxt_switch(adreno_dev, drawctxt, flags);
967
968 *timestamp = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
Shubhraprakash Dasc3ad5802012-05-30 18:10:06 -0600969 drawctxt, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700970 &link[0], (cmds - link));
971
972 KGSL_CMD_INFO(device, "ctxt %d g %08x numibs %d ts %d\n",
973 context->id, (unsigned int)ibdesc, numibs, *timestamp);
974
975 kfree(link);
976
977#ifdef CONFIG_MSM_KGSL_CFF_DUMP
978 /*
979 * insert wait for idle after every IB1
980 * this is conservative but works reliably and is ok
981 * even for performance simulations
982 */
Jordan Crousea29a2e02012-08-14 09:09:23 -0600983 adreno_idle(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700984#endif
Shubhraprakash Das32240ef2012-06-06 20:27:46 -0600985 /* If context hung and recovered then return error so that the
986 * application may handle it */
987 if (drawctxt->flags & CTXT_FLAGS_GPU_HANG_RECOVERED)
988 return -EDEADLK;
989 else
990 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700991
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700992}
993
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -0600994static int _find_start_of_cmd_seq(struct adreno_ringbuffer *rb,
995 unsigned int *ptr,
996 bool inc)
997{
998 int status = -EINVAL;
999 unsigned int val1;
1000 unsigned int size = rb->buffer_desc.size;
1001 unsigned int start_ptr = *ptr;
1002
1003 while ((start_ptr / sizeof(unsigned int)) != rb->wptr) {
1004 if (inc)
1005 start_ptr = adreno_ringbuffer_inc_wrapped(start_ptr,
1006 size);
1007 else
1008 start_ptr = adreno_ringbuffer_dec_wrapped(start_ptr,
1009 size);
1010 kgsl_sharedmem_readl(&rb->buffer_desc, &val1, start_ptr);
1011 if (KGSL_CMD_IDENTIFIER == val1) {
1012 if ((start_ptr / sizeof(unsigned int)) != rb->wptr)
1013 start_ptr = adreno_ringbuffer_dec_wrapped(
1014 start_ptr, size);
1015 *ptr = start_ptr;
1016 status = 0;
1017 break;
1018 }
1019 }
1020 return status;
1021}
1022
1023static int _find_cmd_seq_after_eop_ts(struct adreno_ringbuffer *rb,
1024 unsigned int *rb_rptr,
1025 unsigned int global_eop,
1026 bool inc)
1027{
1028 int status = -EINVAL;
1029 unsigned int temp_rb_rptr = *rb_rptr;
1030 unsigned int size = rb->buffer_desc.size;
1031 unsigned int val[3];
1032 int i = 0;
1033 bool check = false;
1034
1035 if (inc && temp_rb_rptr / sizeof(unsigned int) != rb->wptr)
1036 return status;
1037
1038 do {
1039 /* when decrementing we need to decrement first and
1040 * then read make sure we cover all the data */
1041 if (!inc)
1042 temp_rb_rptr = adreno_ringbuffer_dec_wrapped(
1043 temp_rb_rptr, size);
1044 kgsl_sharedmem_readl(&rb->buffer_desc, &val[i],
1045 temp_rb_rptr);
1046
1047 if (check && ((inc && val[i] == global_eop) ||
1048 (!inc && (val[i] ==
1049 cp_type3_packet(CP_MEM_WRITE, 2) ||
1050 val[i] == CACHE_FLUSH_TS)))) {
1051 /* decrement i, i.e i = (i - 1 + 3) % 3 if
1052 * we are going forward, else increment i */
1053 i = (i + 2) % 3;
1054 if (val[i] == rb->device->memstore.gpuaddr +
1055 KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
1056 eoptimestamp)) {
1057 int j = ((i + 2) % 3);
1058 if ((inc && (val[j] == CACHE_FLUSH_TS ||
1059 val[j] == cp_type3_packet(
1060 CP_MEM_WRITE, 2))) ||
1061 (!inc && val[j] == global_eop)) {
1062 /* Found the global eop */
1063 status = 0;
1064 break;
1065 }
1066 }
1067 /* if no match found then increment i again
1068 * since we decremented before matching */
1069 i = (i + 1) % 3;
1070 }
1071 if (inc)
1072 temp_rb_rptr = adreno_ringbuffer_inc_wrapped(
1073 temp_rb_rptr, size);
1074
1075 i = (i + 1) % 3;
1076 if (2 == i)
1077 check = true;
1078 } while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr);
Shubhraprakash Das6f6ecb32012-06-13 12:17:11 -06001079 /* temp_rb_rptr points to the command stream after global eop,
1080 * move backward till the start of command sequence */
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001081 if (!status) {
Shubhraprakash Das6f6ecb32012-06-13 12:17:11 -06001082 status = _find_start_of_cmd_seq(rb, &temp_rb_rptr, false);
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001083 if (!status) {
1084 *rb_rptr = temp_rb_rptr;
1085 KGSL_DRV_ERR(rb->device,
1086 "Offset of cmd sequence after eop timestamp: 0x%x\n",
1087 temp_rb_rptr / sizeof(unsigned int));
1088 }
1089 }
Shubhraprakash Das32240ef2012-06-06 20:27:46 -06001090 if (status)
1091 KGSL_DRV_ERR(rb->device,
1092 "Failed to find the command sequence after eop timestamp\n");
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001093 return status;
1094}
1095
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001096static int _find_hanging_ib_sequence(struct adreno_ringbuffer *rb,
1097 unsigned int *rb_rptr,
1098 unsigned int ib1)
1099{
1100 int status = -EINVAL;
1101 unsigned int temp_rb_rptr = *rb_rptr;
1102 unsigned int size = rb->buffer_desc.size;
1103 unsigned int val[2];
1104 int i = 0;
1105 bool check = false;
1106 bool ctx_switch = false;
1107
1108 while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
1109 kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
1110
1111 if (check && val[i] == ib1) {
1112 /* decrement i, i.e i = (i - 1 + 2) % 2 */
1113 i = (i + 1) % 2;
1114 if (adreno_cmd_is_ib(val[i])) {
1115 /* go till start of command sequence */
1116 status = _find_start_of_cmd_seq(rb,
1117 &temp_rb_rptr, false);
1118 KGSL_DRV_ERR(rb->device,
1119 "Found the hanging IB at offset 0x%x\n",
1120 temp_rb_rptr / sizeof(unsigned int));
1121 break;
1122 }
1123 /* if no match the increment i since we decremented
1124 * before checking */
1125 i = (i + 1) % 2;
1126 }
1127 /* Make sure you do not encounter a context switch twice, we can
1128 * encounter it once for the bad context as the start of search
1129 * can point to the context switch */
1130 if (val[i] == KGSL_CONTEXT_TO_MEM_IDENTIFIER) {
1131 if (ctx_switch) {
1132 KGSL_DRV_ERR(rb->device,
1133 "Context switch encountered before bad "
1134 "IB found\n");
1135 break;
1136 }
1137 ctx_switch = true;
1138 }
1139 i = (i + 1) % 2;
1140 if (1 == i)
1141 check = true;
1142 temp_rb_rptr = adreno_ringbuffer_inc_wrapped(temp_rb_rptr,
1143 size);
1144 }
1145 if (!status)
1146 *rb_rptr = temp_rb_rptr;
1147 return status;
1148}
1149
1150static void _turn_preamble_on_for_ib_seq(struct adreno_ringbuffer *rb,
1151 unsigned int rb_rptr)
1152{
1153 unsigned int temp_rb_rptr = rb_rptr;
1154 unsigned int size = rb->buffer_desc.size;
1155 unsigned int val[2];
1156 int i = 0;
1157 bool check = false;
1158 bool cmd_start = false;
1159
1160 /* Go till the start of the ib sequence and turn on preamble */
1161 while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
1162 kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
1163 if (check && KGSL_START_OF_IB_IDENTIFIER == val[i]) {
1164 /* decrement i */
1165 i = (i + 1) % 2;
1166 if (val[i] == cp_nop_packet(4)) {
1167 temp_rb_rptr = adreno_ringbuffer_dec_wrapped(
1168 temp_rb_rptr, size);
1169 kgsl_sharedmem_writel(&rb->buffer_desc,
1170 temp_rb_rptr, cp_nop_packet(1));
1171 }
1172 KGSL_DRV_ERR(rb->device,
1173 "Turned preamble on at offset 0x%x\n",
1174 temp_rb_rptr / 4);
1175 break;
1176 }
1177 /* If you reach beginning of next command sequence then exit
1178 * First command encountered is the current one so don't break
1179 * on that. */
1180 if (KGSL_CMD_IDENTIFIER == val[i]) {
1181 if (cmd_start)
1182 break;
1183 cmd_start = true;
1184 }
1185
1186 i = (i + 1) % 2;
1187 if (1 == i)
1188 check = true;
1189 temp_rb_rptr = adreno_ringbuffer_inc_wrapped(temp_rb_rptr,
1190 size);
1191 }
1192}
1193
Shubhraprakash Das1d577fe2012-05-31 18:28:22 -06001194static void _copy_valid_rb_content(struct adreno_ringbuffer *rb,
1195 unsigned int rb_rptr, unsigned int *temp_rb_buffer,
1196 int *rb_size, unsigned int *bad_rb_buffer,
1197 int *bad_rb_size,
1198 int *last_valid_ctx_id)
1199{
1200 unsigned int good_rb_idx = 0, cmd_start_idx = 0;
1201 unsigned int val1 = 0;
1202 struct kgsl_context *k_ctxt;
1203 struct adreno_context *a_ctxt;
1204 unsigned int bad_rb_idx = 0;
1205 int copy_rb_contents = 0;
1206 unsigned int temp_rb_rptr;
1207 unsigned int size = rb->buffer_desc.size;
1208 unsigned int good_cmd_start_idx = 0;
1209
1210 /* Walk the rb from the context switch. Omit any commands
1211 * for an invalid context. */
1212 while ((rb_rptr / sizeof(unsigned int)) != rb->wptr) {
1213 kgsl_sharedmem_readl(&rb->buffer_desc, &val1, rb_rptr);
1214
1215 if (KGSL_CMD_IDENTIFIER == val1) {
1216 /* Start is the NOP dword that comes before
1217 * KGSL_CMD_IDENTIFIER */
1218 cmd_start_idx = bad_rb_idx - 1;
1219 if (copy_rb_contents)
1220 good_cmd_start_idx = good_rb_idx - 1;
1221 }
1222
1223 /* check for context switch indicator */
1224 if (val1 == KGSL_CONTEXT_TO_MEM_IDENTIFIER) {
1225 unsigned int temp_idx, val2;
1226 /* increment by 3 to get to the context_id */
1227 temp_rb_rptr = rb_rptr + (3 * sizeof(unsigned int)) %
1228 size;
1229 kgsl_sharedmem_readl(&rb->buffer_desc, &val2,
1230 temp_rb_rptr);
1231
1232 /* if context switches to a context that did not cause
1233 * hang then start saving the rb contents as those
1234 * commands can be executed */
1235 k_ctxt = idr_find(&rb->device->context_idr, val2);
1236 if (k_ctxt) {
1237 a_ctxt = k_ctxt->devctxt;
1238
1239 /* If we are changing to a good context and were not
1240 * copying commands then copy over commands to the good
1241 * context */
1242 if (!copy_rb_contents && ((k_ctxt &&
1243 !(a_ctxt->flags & CTXT_FLAGS_GPU_HANG)) ||
1244 !k_ctxt)) {
1245 for (temp_idx = cmd_start_idx;
1246 temp_idx < bad_rb_idx;
1247 temp_idx++)
1248 temp_rb_buffer[good_rb_idx++] =
1249 bad_rb_buffer[temp_idx];
1250 *last_valid_ctx_id = val2;
1251 copy_rb_contents = 1;
1252 } else if (copy_rb_contents && k_ctxt &&
1253 (a_ctxt->flags & CTXT_FLAGS_GPU_HANG)) {
1254 /* If we are changing to bad context then remove
1255 * the dwords we copied for this sequence from
1256 * the good buffer */
1257 good_rb_idx = good_cmd_start_idx;
1258 copy_rb_contents = 0;
1259 }
1260 }
1261 }
1262
1263 if (copy_rb_contents)
1264 temp_rb_buffer[good_rb_idx++] = val1;
1265 /* Copy both good and bad commands for replay to the bad
1266 * buffer */
1267 bad_rb_buffer[bad_rb_idx++] = val1;
1268
1269 rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr, size);
1270 }
1271 *rb_size = good_rb_idx;
1272 *bad_rb_size = bad_rb_idx;
1273}
1274
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001275int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
Shubhraprakash Dasba6c70b2012-05-31 02:53:06 -06001276 struct adreno_recovery_data *rec_data)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001277{
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001278 int status;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001279 struct kgsl_device *device = rb->device;
Shubhraprakash Dasadb16022012-05-31 16:19:37 -06001280 unsigned int rb_rptr = rb->wptr * sizeof(unsigned int);
Carter Cooper7e7f02e2012-02-15 09:36:31 -07001281 struct kgsl_context *context;
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001282 struct adreno_context *adreno_context;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001283
Shubhraprakash Dasadb16022012-05-31 16:19:37 -06001284 context = idr_find(&device->context_idr, rec_data->context_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001285
Shubhraprakash Das6f6ecb32012-06-13 12:17:11 -06001286 /* Look for the command stream that is right after the global eop */
1287 status = _find_cmd_seq_after_eop_ts(rb, &rb_rptr,
1288 rec_data->global_eop + 1, false);
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001289 if (status)
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001290 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001291
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001292 if (context) {
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001293 adreno_context = context->devctxt;
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001294
1295 if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
1296 if (rec_data->ib1) {
1297 status = _find_hanging_ib_sequence(rb, &rb_rptr,
1298 rec_data->ib1);
1299 if (status)
1300 goto copy_rb_contents;
1301 }
1302 _turn_preamble_on_for_ib_seq(rb, rb_rptr);
Shubhraprakash Das32240ef2012-06-06 20:27:46 -06001303 } else {
1304 status = -EINVAL;
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001305 }
1306 }
1307
1308copy_rb_contents:
Shubhraprakash Das1d577fe2012-05-31 18:28:22 -06001309 _copy_valid_rb_content(rb, rb_rptr, rec_data->rb_buffer,
1310 &rec_data->rb_size,
1311 rec_data->bad_rb_buffer,
1312 &rec_data->bad_rb_size,
1313 &rec_data->last_valid_ctx_id);
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001314 /* If we failed to get the hanging IB sequence then we cannot execute
Shubhraprakash Das32240ef2012-06-06 20:27:46 -06001315 * commands from the bad context or preambles not supported */
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001316 if (status) {
1317 rec_data->bad_rb_size = 0;
1318 status = 0;
1319 }
Shubhraprakash Das32240ef2012-06-06 20:27:46 -06001320 /* If there is no context then that means there are no commands for
1321 * good case */
1322 if (!context)
1323 rec_data->rb_size = 0;
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001324done:
1325 return status;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001326}
1327
1328void
1329adreno_ringbuffer_restore(struct adreno_ringbuffer *rb, unsigned int *rb_buff,
1330 int num_rb_contents)
1331{
1332 int i;
1333 unsigned int *ringcmds;
1334 unsigned int rcmd_gpu;
1335
1336 if (!num_rb_contents)
1337 return;
1338
1339 if (num_rb_contents > (rb->buffer_desc.size - rb->wptr)) {
1340 adreno_regwrite(rb->device, REG_CP_RB_RPTR, 0);
1341 rb->rptr = 0;
1342 BUG_ON(num_rb_contents > rb->buffer_desc.size);
1343 }
1344 ringcmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
1345 rcmd_gpu = rb->buffer_desc.gpuaddr + sizeof(unsigned int) * rb->wptr;
1346 for (i = 0; i < num_rb_contents; i++)
1347 GSL_RB_WRITE(ringcmds, rcmd_gpu, rb_buff[i]);
1348 rb->wptr += num_rb_contents;
1349 adreno_ringbuffer_submit(rb);
1350}