blob: 53e40c9e690656b1a6c1582cf4adefe91fca9c17 [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 Crousef50bfdc2012-11-01 13:48:35 -060031/*
32 * CP DEBUG settings for all cores:
33 * DYNAMIC_CLK_DISABLE [27] - turn off the dynamic clock control
34 * PROG_END_PTR_ENABLE [25] - Allow 128 bit writes to the VBIF
35 */
36
37#define CP_DEBUG_DEFAULT ((1 << 27) | (1 << 25))
38
Jordan Crouseb4d31bd2012-02-01 22:11:12 -070039void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040{
41 BUG_ON(rb->wptr == 0);
42
Lucille Sylvester958dc942011-09-06 18:19:49 -060043 /* Let the pwrscale policy know that new commands have
44 been submitted. */
45 kgsl_pwrscale_busy(rb->device);
46
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070047 /*synchronize memory before informing the hardware of the
48 *new commands.
49 */
50 mb();
51
52 adreno_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr);
53}
54
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -070055static int
56adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb,
57 struct adreno_context *context,
58 unsigned int numcmds, int wptr_ahead)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059{
60 int nopcount;
61 unsigned int freecmds;
62 unsigned int *cmds;
63 uint cmds_gpu;
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -060064 unsigned long wait_time;
Jordan Crouse21f75a02012-08-09 15:08:59 -060065 unsigned long wait_timeout = msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
Tarun Karra3335f142012-06-19 14:11:48 -070066 unsigned long wait_time_part;
Tarun Karra3335f142012-06-19 14:11:48 -070067 unsigned int prev_reg_val[hang_detect_regs_count];
68
69 memset(prev_reg_val, 0, sizeof(prev_reg_val));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070070
71 /* if wptr ahead, fill the remaining with NOPs */
72 if (wptr_ahead) {
73 /* -1 for header */
74 nopcount = rb->sizedwords - rb->wptr - 1;
75
76 cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
77 cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*rb->wptr;
78
Jordan Crouse084427d2011-07-28 08:37:58 -060079 GSL_RB_WRITE(cmds, cmds_gpu, cp_nop_packet(nopcount));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070080
81 /* Make sure that rptr is not 0 before submitting
82 * commands at the end of ringbuffer. We do not
83 * want the rptr and wptr to become equal when
84 * the ringbuffer is not empty */
85 do {
86 GSL_RB_GET_READPTR(rb, &rb->rptr);
87 } while (!rb->rptr);
88
89 rb->wptr++;
90
91 adreno_ringbuffer_submit(rb);
92
93 rb->wptr = 0;
94 }
95
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -060096 wait_time = jiffies + wait_timeout;
Jordan Crouse21f75a02012-08-09 15:08:59 -060097 wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070098 /* wait for space in ringbuffer */
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -060099 while (1) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700100 GSL_RB_GET_READPTR(rb, &rb->rptr);
101
102 freecmds = rb->rptr - rb->wptr;
103
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600104 if (freecmds == 0 || freecmds > numcmds)
105 break;
106
Tarun Karra3335f142012-06-19 14:11:48 -0700107 /* Dont wait for timeout, detect hang faster.
108 */
109 if (time_after(jiffies, wait_time_part)) {
110 wait_time_part = jiffies +
Jordan Crouse21f75a02012-08-09 15:08:59 -0600111 msecs_to_jiffies(KGSL_TIMEOUT_PART);
Tarun Karra3335f142012-06-19 14:11:48 -0700112 if ((adreno_hang_detect(rb->device,
113 prev_reg_val))){
114 KGSL_DRV_ERR(rb->device,
115 "Hang detected while waiting for freespace in"
116 "ringbuffer rptr: 0x%x, wptr: 0x%x\n",
117 rb->rptr, rb->wptr);
118 goto err;
119 }
120 }
121
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600122 if (time_after(jiffies, wait_time)) {
123 KGSL_DRV_ERR(rb->device,
124 "Timed out while waiting for freespace in ringbuffer "
125 "rptr: 0x%x, wptr: 0x%x\n", rb->rptr, rb->wptr);
Tarun Karra3335f142012-06-19 14:11:48 -0700126 goto err;
127 }
128
Wei Zou50ec3372012-07-17 15:46:52 -0700129 continue;
130
Tarun Karra3335f142012-06-19 14:11:48 -0700131err:
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700132 if (!adreno_dump_and_recover(rb->device)) {
133 if (context && context->flags & CTXT_FLAGS_GPU_HANG) {
134 KGSL_CTXT_WARN(rb->device,
135 "Context %p caused a gpu hang. Will not accept commands for context %d\n",
136 context, context->id);
137 return -EDEADLK;
138 }
139 wait_time = jiffies + wait_timeout;
140 } else {
141 /* GPU is hung and we cannot recover */
142 BUG();
143 }
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600144 }
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700145 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700146}
147
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700148unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700149 struct adreno_context *context,
150 unsigned int numcmds)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700151{
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700152 unsigned int *ptr = NULL;
153 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700154 BUG_ON(numcmds >= rb->sizedwords);
155
156 GSL_RB_GET_READPTR(rb, &rb->rptr);
157 /* check for available space */
158 if (rb->wptr >= rb->rptr) {
159 /* wptr ahead or equal to rptr */
160 /* reserve dwords for nop packet */
161 if ((rb->wptr + numcmds) > (rb->sizedwords -
162 GSL_RB_NOP_SIZEDWORDS))
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700163 ret = adreno_ringbuffer_waitspace(rb, context,
164 numcmds, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165 } else {
166 /* wptr behind rptr */
167 if ((rb->wptr + numcmds) >= rb->rptr)
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700168 ret = adreno_ringbuffer_waitspace(rb, context,
169 numcmds, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700170 /* check for remaining space */
171 /* reserve dwords for nop packet */
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700172 if (!ret && (rb->wptr + numcmds) > (rb->sizedwords -
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700173 GSL_RB_NOP_SIZEDWORDS))
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700174 ret = adreno_ringbuffer_waitspace(rb, context,
175 numcmds, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700176 }
177
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700178 if (!ret) {
179 ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
180 rb->wptr += numcmds;
181 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700182
183 return ptr;
184}
185
186static int _load_firmware(struct kgsl_device *device, const char *fwfile,
187 void **data, int *len)
188{
189 const struct firmware *fw = NULL;
190 int ret;
191
192 ret = request_firmware(&fw, fwfile, device->dev);
193
194 if (ret) {
195 KGSL_DRV_ERR(device, "request_firmware(%s) failed: %d\n",
196 fwfile, ret);
197 return ret;
198 }
199
200 *data = kmalloc(fw->size, GFP_KERNEL);
201
202 if (*data) {
203 memcpy(*data, fw->data, fw->size);
204 *len = fw->size;
205 } else
206 KGSL_MEM_ERR(device, "kmalloc(%d) failed\n", fw->size);
207
208 release_firmware(fw);
209 return (*data != NULL) ? 0 : -ENOMEM;
210}
211
212static int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device)
213{
214 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700215 int i, ret = 0;
216
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700217 if (adreno_dev->pm4_fw == NULL) {
218 int len;
Jordan Crouse505df9c2011-07-28 08:37:59 -0600219 void *ptr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700220
Jordan Crouse505df9c2011-07-28 08:37:59 -0600221 ret = _load_firmware(device, adreno_dev->pm4_fwfile,
222 &ptr, &len);
223
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700224 if (ret)
225 goto err;
226
227 /* PM4 size is 3 dword aligned plus 1 dword of version */
228 if (len % ((sizeof(uint32_t) * 3)) != sizeof(uint32_t)) {
229 KGSL_DRV_ERR(device, "Bad firmware size: %d\n", len);
230 ret = -EINVAL;
Jeremy Gebben79acee62011-08-08 16:44:07 -0600231 kfree(ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700232 goto err;
233 }
234
235 adreno_dev->pm4_fw_size = len / sizeof(uint32_t);
236 adreno_dev->pm4_fw = ptr;
237 }
238
239 KGSL_DRV_INFO(device, "loading pm4 ucode version: %d\n",
240 adreno_dev->pm4_fw[0]);
241
Jordan Crousef50bfdc2012-11-01 13:48:35 -0600242 adreno_regwrite(device, REG_CP_DEBUG, CP_DEBUG_DEFAULT);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700243 adreno_regwrite(device, REG_CP_ME_RAM_WADDR, 0);
244 for (i = 1; i < adreno_dev->pm4_fw_size; i++)
245 adreno_regwrite(device, REG_CP_ME_RAM_DATA,
246 adreno_dev->pm4_fw[i]);
247err:
248 return ret;
249}
250
251static int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device)
252{
253 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700254 int i, ret = 0;
255
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700256 if (adreno_dev->pfp_fw == NULL) {
257 int len;
Jordan Crouse505df9c2011-07-28 08:37:59 -0600258 void *ptr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700259
Jordan Crouse505df9c2011-07-28 08:37:59 -0600260 ret = _load_firmware(device, adreno_dev->pfp_fwfile,
261 &ptr, &len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700262 if (ret)
263 goto err;
264
265 /* PFP size shold be dword aligned */
266 if (len % sizeof(uint32_t) != 0) {
267 KGSL_DRV_ERR(device, "Bad firmware size: %d\n", len);
268 ret = -EINVAL;
Jeremy Gebben79acee62011-08-08 16:44:07 -0600269 kfree(ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270 goto err;
271 }
272
273 adreno_dev->pfp_fw_size = len / sizeof(uint32_t);
274 adreno_dev->pfp_fw = ptr;
275 }
276
277 KGSL_DRV_INFO(device, "loading pfp ucode version: %d\n",
278 adreno_dev->pfp_fw[0]);
279
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700280 adreno_regwrite(device, adreno_dev->gpudev->reg_cp_pfp_ucode_addr, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700281 for (i = 1; i < adreno_dev->pfp_fw_size; i++)
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700282 adreno_regwrite(device,
283 adreno_dev->gpudev->reg_cp_pfp_ucode_data,
284 adreno_dev->pfp_fw[i]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700285err:
286 return ret;
287}
288
289int adreno_ringbuffer_start(struct adreno_ringbuffer *rb, unsigned int init_ram)
290{
291 int status;
292 /*cp_rb_cntl_u cp_rb_cntl; */
293 union reg_cp_rb_cntl cp_rb_cntl;
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700294 unsigned int rb_cntl;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700295 struct kgsl_device *device = rb->device;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700296 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700297
298 if (rb->flags & KGSL_FLAGS_STARTED)
299 return 0;
300
Carter Coopercb3e8eb2012-04-11 09:39:40 -0600301 if (init_ram)
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700302 rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700303
304 kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0,
305 sizeof(struct kgsl_rbmemptrs));
306
307 kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA,
308 (rb->sizedwords << 2));
309
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700310 if (adreno_is_a2xx(adreno_dev)) {
311 adreno_regwrite(device, REG_CP_RB_WPTR_BASE,
312 (rb->memptrs_desc.gpuaddr
313 + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700314
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700315 /* setup WPTR delay */
316 adreno_regwrite(device, REG_CP_RB_WPTR_DELAY,
317 0 /*0x70000010 */);
318 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700319
320 /*setup REG_CP_RB_CNTL */
321 adreno_regread(device, REG_CP_RB_CNTL, &rb_cntl);
322 cp_rb_cntl.val = rb_cntl;
323
324 /*
325 * The size of the ringbuffer in the hardware is the log2
326 * representation of the size in quadwords (sizedwords / 2)
327 */
328 cp_rb_cntl.f.rb_bufsz = ilog2(rb->sizedwords >> 1);
329
330 /*
331 * Specify the quadwords to read before updating mem RPTR.
332 * Like above, pass the log2 representation of the blocksize
333 * in quadwords.
334 */
335 cp_rb_cntl.f.rb_blksz = ilog2(KGSL_RB_BLKSIZE >> 3);
336
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700337 if (adreno_is_a2xx(adreno_dev)) {
338 /* WPTR polling */
339 cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN;
340 }
341
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700342 /* mem RPTR writebacks */
343 cp_rb_cntl.f.rb_no_update = GSL_RB_CNTL_NO_UPDATE;
344
345 adreno_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val);
346
347 adreno_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr);
348
349 adreno_regwrite(device, REG_CP_RB_RPTR_ADDR,
350 rb->memptrs_desc.gpuaddr +
351 GSL_RB_MEMPTRS_RPTR_OFFSET);
352
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700353 if (adreno_is_a3xx(adreno_dev)) {
354 /* enable access protection to privileged registers */
355 adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
356
357 /* RBBM registers */
358 adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
359 adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
360 adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
361 adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
362 adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
363 adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);
364
365 /* CP registers */
366 adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
367 adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
368 adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
369 adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
370 adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);
371
372 /* RB registers */
373 adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);
374
375 /* VBIF registers */
376 adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
377 }
378
379 if (adreno_is_a2xx(adreno_dev)) {
380 /* explicitly clear all cp interrupts */
381 adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
382 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700383
384 /* setup scratch/timestamp */
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700385 adreno_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr +
386 KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
387 soptimestamp));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700388
389 adreno_regwrite(device, REG_SCRATCH_UMSK,
390 GSL_RB_MEMPTRS_SCRATCH_MASK);
391
392 /* load the CP ucode */
393
394 status = adreno_ringbuffer_load_pm4_ucode(device);
395 if (status != 0)
396 return status;
397
398 /* load the prefetch parser ucode */
399 status = adreno_ringbuffer_load_pfp_ucode(device);
400 if (status != 0)
401 return status;
402
Kevin Matlageff806df2012-05-07 18:13:21 -0600403 /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
Kevin Matlagee8d35862012-04-26 12:58:15 -0600404 if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev))
Kevin Matlageff806df2012-05-07 18:13:21 -0600405 adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700406
407 rb->rptr = 0;
408 rb->wptr = 0;
409
410 /* clear ME_HALT to start micro engine */
411 adreno_regwrite(device, REG_CP_ME_CNTL, 0);
412
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700413 /* ME init is GPU specific, so jump into the sub-function */
414 adreno_dev->gpudev->rb_init(adreno_dev, rb);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700415
416 /* idle device to validate ME INIT */
Jordan Crousea29a2e02012-08-14 09:09:23 -0600417 status = adreno_idle(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700418
419 if (status == 0)
420 rb->flags |= KGSL_FLAGS_STARTED;
421
422 return status;
423}
424
Carter Cooper6dd94c82011-10-13 14:43:53 -0600425void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700426{
Rajeev Kulkarnibf7a3822012-08-14 21:21:14 +0530427 struct kgsl_device *device = rb->device;
428 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
429
430 if (rb->flags & KGSL_FLAGS_STARTED) {
431 if (adreno_is_a200(adreno_dev))
432 adreno_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000);
433
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700434 rb->flags &= ~KGSL_FLAGS_STARTED;
Rajeev Kulkarnibf7a3822012-08-14 21:21:14 +0530435 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700436}
437
438int adreno_ringbuffer_init(struct kgsl_device *device)
439{
440 int status;
441 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
442 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
443
444 rb->device = device;
445 /*
446 * It is silly to convert this to words and then back to bytes
447 * immediately below, but most of the rest of the code deals
448 * in words, so we might as well only do the math once
449 */
450 rb->sizedwords = KGSL_RB_SIZE >> 2;
451
452 /* allocate memory for ringbuffer */
453 status = kgsl_allocate_contiguous(&rb->buffer_desc,
454 (rb->sizedwords << 2));
455
456 if (status != 0) {
457 adreno_ringbuffer_close(rb);
458 return status;
459 }
460
461 /* allocate memory for polling and timestamps */
462 /* This really can be at 4 byte alignment boundry but for using MMU
463 * we need to make it at page boundary */
464 status = kgsl_allocate_contiguous(&rb->memptrs_desc,
465 sizeof(struct kgsl_rbmemptrs));
466
467 if (status != 0) {
468 adreno_ringbuffer_close(rb);
469 return status;
470 }
471
472 /* overlay structure on memptrs memory */
473 rb->memptrs = (struct kgsl_rbmemptrs *) rb->memptrs_desc.hostptr;
474
475 return 0;
476}
477
Carter Cooper6dd94c82011-10-13 14:43:53 -0600478void adreno_ringbuffer_close(struct adreno_ringbuffer *rb)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700479{
480 struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
481
482 kgsl_sharedmem_free(&rb->buffer_desc);
483 kgsl_sharedmem_free(&rb->memptrs_desc);
484
485 kfree(adreno_dev->pfp_fw);
486 kfree(adreno_dev->pm4_fw);
487
488 adreno_dev->pfp_fw = NULL;
489 adreno_dev->pm4_fw = NULL;
490
491 memset(rb, 0, sizeof(struct adreno_ringbuffer));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700492}
493
494static uint32_t
495adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700496 struct adreno_context *context,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700497 unsigned int flags, unsigned int *cmds,
498 int sizedwords)
499{
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700500 struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700501 unsigned int *ringcmds;
502 unsigned int timestamp;
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700503 unsigned int total_sizedwords = sizedwords;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700504 unsigned int i;
505 unsigned int rcmd_gpu;
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700506 unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
507 unsigned int gpuaddr = rb->device->memstore.gpuaddr;
508
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600509 /*
510 * if the context was not created with per context timestamp
511 * support, we must use the global timestamp since issueibcmds
512 * will be returning that one.
513 */
514 if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)
515 context_id = context->id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700516
517 /* reserve space to temporarily turn off protected mode
518 * error checking if needed
519 */
520 total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
Shubhraprakash Dasc3ad5802012-05-30 18:10:06 -0600521 /* 2 dwords to store the start of command sequence */
522 total_sizedwords += 2;
Carter Cooperbd5c9fc2012-11-02 11:17:55 -0600523
524 /* Add CP_COND_EXEC commands to generate CP_INTERRUPT */
Carter Cooper7ffaba62012-05-24 13:59:53 -0600525 total_sizedwords += context ? 7 : 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700526
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700527 if (adreno_is_a3xx(adreno_dev))
528 total_sizedwords += 7;
529
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700530 total_sizedwords += 2; /* scratchpad ts for recovery */
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600531 if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700532 total_sizedwords += 3; /* sop timestamp */
533 total_sizedwords += 4; /* eop timestamp */
Rajesh Kemisettic5699302012-04-21 21:09:05 +0530534 total_sizedwords += 3; /* global timestamp without cache
535 * flush for non-zero context */
536 } else {
537 total_sizedwords += 4; /* global timestamp for recovery*/
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700538 }
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700539
Shubhraprakash Dasd316ff82012-08-02 12:43:48 -0700540 ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
541 if (!ringcmds) {
542 /*
543 * We could not allocate space in ringbuffer, just return the
544 * last timestamp
545 */
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600546 return rb->timestamp[context_id];
547 }
548
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700549 rcmd_gpu = rb->buffer_desc.gpuaddr
550 + sizeof(uint)*(rb->wptr-total_sizedwords);
551
Shubhraprakash Dasc3ad5802012-05-30 18:10:06 -0600552 GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
553 GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
554
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700555 if (flags & KGSL_CMD_FLAGS_PMODE) {
556 /* disable protected mode error checking */
557 GSL_RB_WRITE(ringcmds, rcmd_gpu,
Jordan Crouse084427d2011-07-28 08:37:58 -0600558 cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700559 GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
560 }
561
562 for (i = 0; i < sizedwords; i++) {
563 GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds);
564 cmds++;
565 }
566
567 if (flags & KGSL_CMD_FLAGS_PMODE) {
568 /* re-enable protected mode error checking */
569 GSL_RB_WRITE(ringcmds, rcmd_gpu,
Jordan Crouse084427d2011-07-28 08:37:58 -0600570 cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700571 GSL_RB_WRITE(ringcmds, rcmd_gpu, 1);
572 }
573
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700574 /* always increment the global timestamp. once. */
575 rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
Carter Cooper7ffaba62012-05-24 13:59:53 -0600576
577 if (context && !(flags & KGSL_CMD_FLAGS_DUMMY_INTR_CMD)) {
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700578 if (context_id == KGSL_MEMSTORE_GLOBAL)
Carter Cooper7ffaba62012-05-24 13:59:53 -0600579 rb->timestamp[context->id] =
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700580 rb->timestamp[KGSL_MEMSTORE_GLOBAL];
581 else
582 rb->timestamp[context_id]++;
583 }
584 timestamp = rb->timestamp[context_id];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700585
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700586 /* scratchpad ts for recovery */
Jordan Crouse084427d2011-07-28 08:37:58 -0600587 GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700588 GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700589
590 if (adreno_is_a3xx(adreno_dev)) {
591 /*
592 * FLush HLSQ lazy updates to make sure there are no
593 * rsources pending for indirect loads after the timestamp
594 */
595
596 GSL_RB_WRITE(ringcmds, rcmd_gpu,
597 cp_type3_packet(CP_EVENT_WRITE, 1));
598 GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); /* HLSQ_FLUSH */
599 GSL_RB_WRITE(ringcmds, rcmd_gpu,
600 cp_type3_packet(CP_WAIT_FOR_IDLE, 1));
601 GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
602 }
603
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600604 if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700605 /* start-of-pipeline timestamp */
606 GSL_RB_WRITE(ringcmds, rcmd_gpu,
607 cp_type3_packet(CP_MEM_WRITE, 2));
608 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
Carter Cooper7ffaba62012-05-24 13:59:53 -0600609 KGSL_MEMSTORE_OFFSET(context_id, soptimestamp)));
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700610 GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
611
612 /* end-of-pipeline timestamp */
613 GSL_RB_WRITE(ringcmds, rcmd_gpu,
614 cp_type3_packet(CP_EVENT_WRITE, 3));
615 GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
616 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
Carter Cooper7ffaba62012-05-24 13:59:53 -0600617 KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp)));
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700618 GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700619
Rajesh Kemisettic5699302012-04-21 21:09:05 +0530620 GSL_RB_WRITE(ringcmds, rcmd_gpu,
621 cp_type3_packet(CP_MEM_WRITE, 2));
622 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
Carter Cooper7ffaba62012-05-24 13:59:53 -0600623 KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
624 eoptimestamp)));
Rajesh Kemisettic5699302012-04-21 21:09:05 +0530625 GSL_RB_WRITE(ringcmds, rcmd_gpu,
626 rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
627 } else {
628 GSL_RB_WRITE(ringcmds, rcmd_gpu,
629 cp_type3_packet(CP_EVENT_WRITE, 3));
630 GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
631 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
Carter Cooper7ffaba62012-05-24 13:59:53 -0600632 KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp)));
633 GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[context_id]);
Rajesh Kemisettic5699302012-04-21 21:09:05 +0530634 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700635
Carter Cooper7ffaba62012-05-24 13:59:53 -0600636 if (context) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700637 /* Conditional execution based on memory values */
638 GSL_RB_WRITE(ringcmds, rcmd_gpu,
Jordan Crouse084427d2011-07-28 08:37:58 -0600639 cp_type3_packet(CP_COND_EXEC, 4));
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700640 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
641 KGSL_MEMSTORE_OFFSET(
642 context_id, ts_cmp_enable)) >> 2);
643 GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
644 KGSL_MEMSTORE_OFFSET(
645 context_id, ref_wait_ts)) >> 2);
646 GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700647 /* # of conditional command DWORDs */
648 GSL_RB_WRITE(ringcmds, rcmd_gpu, 2);
649 GSL_RB_WRITE(ringcmds, rcmd_gpu,
Jordan Crouse084427d2011-07-28 08:37:58 -0600650 cp_type3_packet(CP_INTERRUPT, 1));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651 GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK);
652 }
653
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700654 if (adreno_is_a3xx(adreno_dev)) {
655 /* Dummy set-constant to trigger context rollover */
656 GSL_RB_WRITE(ringcmds, rcmd_gpu,
657 cp_type3_packet(CP_SET_CONSTANT, 2));
658 GSL_RB_WRITE(ringcmds, rcmd_gpu,
659 (0x4<<16)|(A3XX_HLSQ_CL_KERNEL_GROUP_X_REG - 0x2000));
660 GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
661 }
662
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700663 adreno_ringbuffer_submit(rb);
664
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700665 return timestamp;
666}
667
Carter Cooper7ffaba62012-05-24 13:59:53 -0600668void
669adreno_ringbuffer_issuecmds_intr(struct kgsl_device *device,
670 struct kgsl_context *k_ctxt,
671 unsigned int *cmds,
672 int sizedwords)
673{
674 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
675 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
676 struct adreno_context *a_ctxt = NULL;
677
678 if (!k_ctxt)
679 return;
680
681 a_ctxt = k_ctxt->devctxt;
682
683 if (k_ctxt->id == KGSL_CONTEXT_INVALID ||
684 a_ctxt == NULL ||
685 device->state & KGSL_STATE_HUNG)
686 return;
687
688 adreno_ringbuffer_addcmds(rb, a_ctxt, KGSL_CMD_FLAGS_DUMMY_INTR_CMD,
689 cmds, sizedwords);
690}
691
Shubhraprakash Dascb068072012-06-07 17:52:41 -0600692unsigned int
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700693adreno_ringbuffer_issuecmds(struct kgsl_device *device,
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600694 struct adreno_context *drawctxt,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700695 unsigned int flags,
696 unsigned int *cmds,
697 int sizedwords)
698{
699 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
700 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
701
702 if (device->state & KGSL_STATE_HUNG)
Shubhraprakash Dascb068072012-06-07 17:52:41 -0600703 return kgsl_readtimestamp(device, KGSL_MEMSTORE_GLOBAL,
704 KGSL_TIMESTAMP_RETIRED);
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600705 return adreno_ringbuffer_addcmds(rb, drawctxt, flags, cmds, sizedwords);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700706}
707
Jeremy Gebbend0ab6ad2012-04-06 11:13:35 -0600708static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
709 int sizedwords);
710
711static bool
712_handle_type3(struct kgsl_device_private *dev_priv, uint *hostaddr)
713{
714 unsigned int opcode = cp_type3_opcode(*hostaddr);
715 switch (opcode) {
716 case CP_INDIRECT_BUFFER_PFD:
717 case CP_INDIRECT_BUFFER_PFE:
718 case CP_COND_INDIRECT_BUFFER_PFE:
719 case CP_COND_INDIRECT_BUFFER_PFD:
720 return _parse_ibs(dev_priv, hostaddr[1], hostaddr[2]);
721 case CP_NOP:
722 case CP_WAIT_FOR_IDLE:
723 case CP_WAIT_REG_MEM:
724 case CP_WAIT_REG_EQ:
725 case CP_WAT_REG_GTE:
726 case CP_WAIT_UNTIL_READ:
727 case CP_WAIT_IB_PFD_COMPLETE:
728 case CP_REG_RMW:
729 case CP_REG_TO_MEM:
730 case CP_MEM_WRITE:
731 case CP_MEM_WRITE_CNTR:
732 case CP_COND_EXEC:
733 case CP_COND_WRITE:
734 case CP_EVENT_WRITE:
735 case CP_EVENT_WRITE_SHD:
736 case CP_EVENT_WRITE_CFL:
737 case CP_EVENT_WRITE_ZPD:
738 case CP_DRAW_INDX:
739 case CP_DRAW_INDX_2:
740 case CP_DRAW_INDX_BIN:
741 case CP_DRAW_INDX_2_BIN:
742 case CP_VIZ_QUERY:
743 case CP_SET_STATE:
744 case CP_SET_CONSTANT:
745 case CP_IM_LOAD:
746 case CP_IM_LOAD_IMMEDIATE:
747 case CP_LOAD_CONSTANT_CONTEXT:
748 case CP_INVALIDATE_STATE:
749 case CP_SET_SHADER_BASES:
750 case CP_SET_BIN_MASK:
751 case CP_SET_BIN_SELECT:
752 case CP_SET_BIN_BASE_OFFSET:
753 case CP_SET_BIN_DATA:
754 case CP_CONTEXT_UPDATE:
755 case CP_INTERRUPT:
756 case CP_IM_STORE:
757 case CP_LOAD_STATE:
758 break;
759 /* these shouldn't come from userspace */
760 case CP_ME_INIT:
761 case CP_SET_PROTECTED_MODE:
762 default:
763 KGSL_CMD_ERR(dev_priv->device, "bad CP opcode %0x\n", opcode);
764 return false;
765 break;
766 }
767
768 return true;
769}
770
771static bool
772_handle_type0(struct kgsl_device_private *dev_priv, uint *hostaddr)
773{
774 unsigned int reg = type0_pkt_offset(*hostaddr);
775 unsigned int cnt = type0_pkt_size(*hostaddr);
776 if (reg < 0x0192 || (reg + cnt) >= 0x8000) {
777 KGSL_CMD_ERR(dev_priv->device, "bad type0 reg: 0x%0x cnt: %d\n",
778 reg, cnt);
779 return false;
780 }
781 return true;
782}
783
784/*
785 * Traverse IBs and dump them to test vector. Detect swap by inspecting
786 * register writes, keeping note of the current state, and dump
787 * framebuffer config to test vector
788 */
789static bool _parse_ibs(struct kgsl_device_private *dev_priv,
790 uint gpuaddr, int sizedwords)
791{
792 static uint level; /* recursion level */
793 bool ret = false;
794 uint *hostaddr, *hoststart;
795 int dwords_left = sizedwords; /* dwords left in the current command
796 buffer */
797 struct kgsl_mem_entry *entry;
798
799 spin_lock(&dev_priv->process_priv->mem_lock);
800 entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
801 gpuaddr, sizedwords * sizeof(uint));
802 spin_unlock(&dev_priv->process_priv->mem_lock);
803 if (entry == NULL) {
804 KGSL_CMD_ERR(dev_priv->device,
805 "no mapping for gpuaddr: 0x%08x\n", gpuaddr);
806 return false;
807 }
808
809 hostaddr = (uint *)kgsl_gpuaddr_to_vaddr(&entry->memdesc, gpuaddr);
810 if (hostaddr == NULL) {
811 KGSL_CMD_ERR(dev_priv->device,
812 "no mapping for gpuaddr: 0x%08x\n", gpuaddr);
813 return false;
814 }
815
816 hoststart = hostaddr;
817
818 level++;
819
820 KGSL_CMD_INFO(dev_priv->device, "ib: gpuaddr:0x%08x, wc:%d, hptr:%p\n",
821 gpuaddr, sizedwords, hostaddr);
822
823 mb();
824 while (dwords_left > 0) {
825 bool cur_ret = true;
826 int count = 0; /* dword count including packet header */
827
828 switch (*hostaddr >> 30) {
829 case 0x0: /* type-0 */
830 count = (*hostaddr >> 16)+2;
831 cur_ret = _handle_type0(dev_priv, hostaddr);
832 break;
833 case 0x1: /* type-1 */
834 count = 2;
835 break;
836 case 0x3: /* type-3 */
837 count = ((*hostaddr >> 16) & 0x3fff) + 2;
838 cur_ret = _handle_type3(dev_priv, hostaddr);
839 break;
840 default:
841 KGSL_CMD_ERR(dev_priv->device, "unexpected type: "
842 "type:%d, word:0x%08x @ 0x%p, gpu:0x%08x\n",
843 *hostaddr >> 30, *hostaddr, hostaddr,
844 gpuaddr+4*(sizedwords-dwords_left));
845 cur_ret = false;
846 count = dwords_left;
847 break;
848 }
849
850 if (!cur_ret) {
851 KGSL_CMD_ERR(dev_priv->device,
852 "bad sub-type: #:%d/%d, v:0x%08x"
853 " @ 0x%p[gb:0x%08x], level:%d\n",
854 sizedwords-dwords_left, sizedwords, *hostaddr,
855 hostaddr, gpuaddr+4*(sizedwords-dwords_left),
856 level);
857
858 if (ADRENO_DEVICE(dev_priv->device)->ib_check_level
859 >= 2)
860 print_hex_dump(KERN_ERR,
861 level == 1 ? "IB1:" : "IB2:",
862 DUMP_PREFIX_OFFSET, 32, 4, hoststart,
863 sizedwords*4, 0);
864 goto done;
865 }
866
867 /* jump to next packet */
868 dwords_left -= count;
869 hostaddr += count;
870 if (dwords_left < 0) {
871 KGSL_CMD_ERR(dev_priv->device,
872 "bad count: c:%d, #:%d/%d, "
873 "v:0x%08x @ 0x%p[gb:0x%08x], level:%d\n",
874 count, sizedwords-(dwords_left+count),
875 sizedwords, *(hostaddr-count), hostaddr-count,
876 gpuaddr+4*(sizedwords-(dwords_left+count)),
877 level);
878 if (ADRENO_DEVICE(dev_priv->device)->ib_check_level
879 >= 2)
880 print_hex_dump(KERN_ERR,
881 level == 1 ? "IB1:" : "IB2:",
882 DUMP_PREFIX_OFFSET, 32, 4, hoststart,
883 sizedwords*4, 0);
884 goto done;
885 }
886 }
887
888 ret = true;
889done:
890 if (!ret)
891 KGSL_DRV_ERR(dev_priv->device,
892 "parsing failed: gpuaddr:0x%08x, "
893 "host:0x%p, wc:%d\n", gpuaddr, hoststart, sizedwords);
894
895 level--;
896
897 return ret;
898}
899
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700900int
901adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv,
902 struct kgsl_context *context,
903 struct kgsl_ibdesc *ibdesc,
904 unsigned int numibs,
905 uint32_t *timestamp,
906 unsigned int flags)
907{
908 struct kgsl_device *device = dev_priv->device;
909 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
910 unsigned int *link;
911 unsigned int *cmds;
912 unsigned int i;
Jeremy Gebben3c127f52011-08-08 17:04:11 -0600913 struct adreno_context *drawctxt;
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700914 unsigned int start_index = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700915
916 if (device->state & KGSL_STATE_HUNG)
917 return -EBUSY;
918 if (!(adreno_dev->ringbuffer.flags & KGSL_FLAGS_STARTED) ||
Jeremy Gebben3c127f52011-08-08 17:04:11 -0600919 context == NULL || ibdesc == 0 || numibs == 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700920 return -EINVAL;
921
Jeremy Gebben3c127f52011-08-08 17:04:11 -0600922 drawctxt = context->devctxt;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700923
924 if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
925 KGSL_CTXT_WARN(device, "Context %p caused a gpu hang.."
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700926 " will not accept commands for context %d\n",
927 drawctxt, drawctxt->id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700928 return -EDEADLK;
929 }
Shubhraprakash Dasd23ff4b2012-04-05 16:55:54 -0600930
931 cmds = link = kzalloc(sizeof(unsigned int) * (numibs * 3 + 4),
932 GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700933 if (!link) {
Shubhraprakash Dasd23ff4b2012-04-05 16:55:54 -0600934 KGSL_CORE_ERR("kzalloc(%d) failed\n",
935 sizeof(unsigned int) * (numibs * 3 + 4));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700936 return -ENOMEM;
937 }
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700938
939 /*When preamble is enabled, the preamble buffer with state restoration
940 commands are stored in the first node of the IB chain. We can skip that
941 if a context switch hasn't occured */
942
943 if (drawctxt->flags & CTXT_FLAGS_PREAMBLE &&
944 adreno_dev->drawctxt_active == drawctxt)
945 start_index = 1;
946
Shubhraprakash Dasd23ff4b2012-04-05 16:55:54 -0600947 if (!start_index) {
948 *cmds++ = cp_nop_packet(1);
949 *cmds++ = KGSL_START_OF_IB_IDENTIFIER;
950 } else {
951 *cmds++ = cp_nop_packet(4);
952 *cmds++ = KGSL_START_OF_IB_IDENTIFIER;
953 *cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
954 *cmds++ = ibdesc[0].gpuaddr;
955 *cmds++ = ibdesc[0].sizedwords;
956 }
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700957 for (i = start_index; i < numibs; i++) {
Jeremy Gebbend0ab6ad2012-04-06 11:13:35 -0600958 if (unlikely(adreno_dev->ib_check_level >= 1 &&
959 !_parse_ibs(dev_priv, ibdesc[i].gpuaddr,
960 ibdesc[i].sizedwords))) {
961 kfree(link);
962 return -EINVAL;
963 }
Jordan Crouse084427d2011-07-28 08:37:58 -0600964 *cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700965 *cmds++ = ibdesc[i].gpuaddr;
966 *cmds++ = ibdesc[i].sizedwords;
967 }
968
Shubhraprakash Dasd23ff4b2012-04-05 16:55:54 -0600969 *cmds++ = cp_nop_packet(1);
970 *cmds++ = KGSL_END_OF_IB_IDENTIFIER;
971
Shubhraprakash Dasb2abc452012-06-08 16:33:03 -0600972 kgsl_setstate(&device->mmu, context->id,
Shubhraprakash Das767fdda2011-08-15 15:49:45 -0600973 kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700974 device->id));
975
976 adreno_drawctxt_switch(adreno_dev, drawctxt, flags);
977
978 *timestamp = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
Shubhraprakash Dasc3ad5802012-05-30 18:10:06 -0600979 drawctxt, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700980 &link[0], (cmds - link));
981
982 KGSL_CMD_INFO(device, "ctxt %d g %08x numibs %d ts %d\n",
983 context->id, (unsigned int)ibdesc, numibs, *timestamp);
984
985 kfree(link);
986
987#ifdef CONFIG_MSM_KGSL_CFF_DUMP
988 /*
989 * insert wait for idle after every IB1
990 * this is conservative but works reliably and is ok
991 * even for performance simulations
992 */
Jordan Crousea29a2e02012-08-14 09:09:23 -0600993 adreno_idle(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700994#endif
Shubhraprakash Das32240ef2012-06-06 20:27:46 -0600995 /* If context hung and recovered then return error so that the
996 * application may handle it */
997 if (drawctxt->flags & CTXT_FLAGS_GPU_HANG_RECOVERED)
998 return -EDEADLK;
999 else
1000 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001001
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001002}
1003
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001004static int _find_start_of_cmd_seq(struct adreno_ringbuffer *rb,
1005 unsigned int *ptr,
1006 bool inc)
1007{
1008 int status = -EINVAL;
1009 unsigned int val1;
1010 unsigned int size = rb->buffer_desc.size;
1011 unsigned int start_ptr = *ptr;
1012
1013 while ((start_ptr / sizeof(unsigned int)) != rb->wptr) {
1014 if (inc)
1015 start_ptr = adreno_ringbuffer_inc_wrapped(start_ptr,
1016 size);
1017 else
1018 start_ptr = adreno_ringbuffer_dec_wrapped(start_ptr,
1019 size);
1020 kgsl_sharedmem_readl(&rb->buffer_desc, &val1, start_ptr);
1021 if (KGSL_CMD_IDENTIFIER == val1) {
1022 if ((start_ptr / sizeof(unsigned int)) != rb->wptr)
1023 start_ptr = adreno_ringbuffer_dec_wrapped(
1024 start_ptr, size);
1025 *ptr = start_ptr;
1026 status = 0;
1027 break;
1028 }
1029 }
1030 return status;
1031}
1032
1033static int _find_cmd_seq_after_eop_ts(struct adreno_ringbuffer *rb,
1034 unsigned int *rb_rptr,
1035 unsigned int global_eop,
1036 bool inc)
1037{
1038 int status = -EINVAL;
1039 unsigned int temp_rb_rptr = *rb_rptr;
1040 unsigned int size = rb->buffer_desc.size;
1041 unsigned int val[3];
1042 int i = 0;
1043 bool check = false;
1044
1045 if (inc && temp_rb_rptr / sizeof(unsigned int) != rb->wptr)
1046 return status;
1047
1048 do {
1049 /* when decrementing we need to decrement first and
1050 * then read make sure we cover all the data */
1051 if (!inc)
1052 temp_rb_rptr = adreno_ringbuffer_dec_wrapped(
1053 temp_rb_rptr, size);
1054 kgsl_sharedmem_readl(&rb->buffer_desc, &val[i],
1055 temp_rb_rptr);
1056
1057 if (check && ((inc && val[i] == global_eop) ||
1058 (!inc && (val[i] ==
1059 cp_type3_packet(CP_MEM_WRITE, 2) ||
1060 val[i] == CACHE_FLUSH_TS)))) {
1061 /* decrement i, i.e i = (i - 1 + 3) % 3 if
1062 * we are going forward, else increment i */
1063 i = (i + 2) % 3;
1064 if (val[i] == rb->device->memstore.gpuaddr +
1065 KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
1066 eoptimestamp)) {
1067 int j = ((i + 2) % 3);
1068 if ((inc && (val[j] == CACHE_FLUSH_TS ||
1069 val[j] == cp_type3_packet(
1070 CP_MEM_WRITE, 2))) ||
1071 (!inc && val[j] == global_eop)) {
1072 /* Found the global eop */
1073 status = 0;
1074 break;
1075 }
1076 }
1077 /* if no match found then increment i again
1078 * since we decremented before matching */
1079 i = (i + 1) % 3;
1080 }
1081 if (inc)
1082 temp_rb_rptr = adreno_ringbuffer_inc_wrapped(
1083 temp_rb_rptr, size);
1084
1085 i = (i + 1) % 3;
1086 if (2 == i)
1087 check = true;
1088 } while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr);
Shubhraprakash Das6f6ecb32012-06-13 12:17:11 -06001089 /* temp_rb_rptr points to the command stream after global eop,
1090 * move backward till the start of command sequence */
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001091 if (!status) {
Shubhraprakash Das6f6ecb32012-06-13 12:17:11 -06001092 status = _find_start_of_cmd_seq(rb, &temp_rb_rptr, false);
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001093 if (!status) {
1094 *rb_rptr = temp_rb_rptr;
1095 KGSL_DRV_ERR(rb->device,
1096 "Offset of cmd sequence after eop timestamp: 0x%x\n",
1097 temp_rb_rptr / sizeof(unsigned int));
1098 }
1099 }
Shubhraprakash Das32240ef2012-06-06 20:27:46 -06001100 if (status)
1101 KGSL_DRV_ERR(rb->device,
1102 "Failed to find the command sequence after eop timestamp\n");
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001103 return status;
1104}
1105
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001106static int _find_hanging_ib_sequence(struct adreno_ringbuffer *rb,
1107 unsigned int *rb_rptr,
1108 unsigned int ib1)
1109{
1110 int status = -EINVAL;
1111 unsigned int temp_rb_rptr = *rb_rptr;
1112 unsigned int size = rb->buffer_desc.size;
1113 unsigned int val[2];
1114 int i = 0;
1115 bool check = false;
1116 bool ctx_switch = false;
1117
1118 while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
1119 kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
1120
1121 if (check && val[i] == ib1) {
1122 /* decrement i, i.e i = (i - 1 + 2) % 2 */
1123 i = (i + 1) % 2;
1124 if (adreno_cmd_is_ib(val[i])) {
1125 /* go till start of command sequence */
1126 status = _find_start_of_cmd_seq(rb,
1127 &temp_rb_rptr, false);
1128 KGSL_DRV_ERR(rb->device,
1129 "Found the hanging IB at offset 0x%x\n",
1130 temp_rb_rptr / sizeof(unsigned int));
1131 break;
1132 }
1133 /* if no match the increment i since we decremented
1134 * before checking */
1135 i = (i + 1) % 2;
1136 }
1137 /* Make sure you do not encounter a context switch twice, we can
1138 * encounter it once for the bad context as the start of search
1139 * can point to the context switch */
1140 if (val[i] == KGSL_CONTEXT_TO_MEM_IDENTIFIER) {
1141 if (ctx_switch) {
1142 KGSL_DRV_ERR(rb->device,
1143 "Context switch encountered before bad "
1144 "IB found\n");
1145 break;
1146 }
1147 ctx_switch = true;
1148 }
1149 i = (i + 1) % 2;
1150 if (1 == i)
1151 check = true;
1152 temp_rb_rptr = adreno_ringbuffer_inc_wrapped(temp_rb_rptr,
1153 size);
1154 }
1155 if (!status)
1156 *rb_rptr = temp_rb_rptr;
1157 return status;
1158}
1159
1160static void _turn_preamble_on_for_ib_seq(struct adreno_ringbuffer *rb,
1161 unsigned int rb_rptr)
1162{
1163 unsigned int temp_rb_rptr = rb_rptr;
1164 unsigned int size = rb->buffer_desc.size;
1165 unsigned int val[2];
1166 int i = 0;
1167 bool check = false;
1168 bool cmd_start = false;
1169
1170 /* Go till the start of the ib sequence and turn on preamble */
1171 while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
1172 kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
1173 if (check && KGSL_START_OF_IB_IDENTIFIER == val[i]) {
1174 /* decrement i */
1175 i = (i + 1) % 2;
1176 if (val[i] == cp_nop_packet(4)) {
1177 temp_rb_rptr = adreno_ringbuffer_dec_wrapped(
1178 temp_rb_rptr, size);
1179 kgsl_sharedmem_writel(&rb->buffer_desc,
1180 temp_rb_rptr, cp_nop_packet(1));
1181 }
1182 KGSL_DRV_ERR(rb->device,
1183 "Turned preamble on at offset 0x%x\n",
1184 temp_rb_rptr / 4);
1185 break;
1186 }
1187 /* If you reach beginning of next command sequence then exit
1188 * First command encountered is the current one so don't break
1189 * on that. */
1190 if (KGSL_CMD_IDENTIFIER == val[i]) {
1191 if (cmd_start)
1192 break;
1193 cmd_start = true;
1194 }
1195
1196 i = (i + 1) % 2;
1197 if (1 == i)
1198 check = true;
1199 temp_rb_rptr = adreno_ringbuffer_inc_wrapped(temp_rb_rptr,
1200 size);
1201 }
1202}
1203
Shubhraprakash Das1d577fe2012-05-31 18:28:22 -06001204static void _copy_valid_rb_content(struct adreno_ringbuffer *rb,
1205 unsigned int rb_rptr, unsigned int *temp_rb_buffer,
1206 int *rb_size, unsigned int *bad_rb_buffer,
1207 int *bad_rb_size,
1208 int *last_valid_ctx_id)
1209{
1210 unsigned int good_rb_idx = 0, cmd_start_idx = 0;
1211 unsigned int val1 = 0;
1212 struct kgsl_context *k_ctxt;
1213 struct adreno_context *a_ctxt;
1214 unsigned int bad_rb_idx = 0;
1215 int copy_rb_contents = 0;
1216 unsigned int temp_rb_rptr;
1217 unsigned int size = rb->buffer_desc.size;
1218 unsigned int good_cmd_start_idx = 0;
1219
1220 /* Walk the rb from the context switch. Omit any commands
1221 * for an invalid context. */
1222 while ((rb_rptr / sizeof(unsigned int)) != rb->wptr) {
1223 kgsl_sharedmem_readl(&rb->buffer_desc, &val1, rb_rptr);
1224
1225 if (KGSL_CMD_IDENTIFIER == val1) {
1226 /* Start is the NOP dword that comes before
1227 * KGSL_CMD_IDENTIFIER */
1228 cmd_start_idx = bad_rb_idx - 1;
1229 if (copy_rb_contents)
1230 good_cmd_start_idx = good_rb_idx - 1;
1231 }
1232
1233 /* check for context switch indicator */
1234 if (val1 == KGSL_CONTEXT_TO_MEM_IDENTIFIER) {
1235 unsigned int temp_idx, val2;
1236 /* increment by 3 to get to the context_id */
1237 temp_rb_rptr = rb_rptr + (3 * sizeof(unsigned int)) %
1238 size;
1239 kgsl_sharedmem_readl(&rb->buffer_desc, &val2,
1240 temp_rb_rptr);
1241
1242 /* if context switches to a context that did not cause
1243 * hang then start saving the rb contents as those
1244 * commands can be executed */
1245 k_ctxt = idr_find(&rb->device->context_idr, val2);
1246 if (k_ctxt) {
1247 a_ctxt = k_ctxt->devctxt;
1248
1249 /* If we are changing to a good context and were not
1250 * copying commands then copy over commands to the good
1251 * context */
1252 if (!copy_rb_contents && ((k_ctxt &&
1253 !(a_ctxt->flags & CTXT_FLAGS_GPU_HANG)) ||
1254 !k_ctxt)) {
1255 for (temp_idx = cmd_start_idx;
1256 temp_idx < bad_rb_idx;
1257 temp_idx++)
1258 temp_rb_buffer[good_rb_idx++] =
1259 bad_rb_buffer[temp_idx];
1260 *last_valid_ctx_id = val2;
1261 copy_rb_contents = 1;
1262 } else if (copy_rb_contents && k_ctxt &&
1263 (a_ctxt->flags & CTXT_FLAGS_GPU_HANG)) {
1264 /* If we are changing to bad context then remove
1265 * the dwords we copied for this sequence from
1266 * the good buffer */
1267 good_rb_idx = good_cmd_start_idx;
1268 copy_rb_contents = 0;
1269 }
1270 }
1271 }
1272
1273 if (copy_rb_contents)
1274 temp_rb_buffer[good_rb_idx++] = val1;
1275 /* Copy both good and bad commands for replay to the bad
1276 * buffer */
1277 bad_rb_buffer[bad_rb_idx++] = val1;
1278
1279 rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr, size);
1280 }
1281 *rb_size = good_rb_idx;
1282 *bad_rb_size = bad_rb_idx;
1283}
1284
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001285int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
Shubhraprakash Dasba6c70b2012-05-31 02:53:06 -06001286 struct adreno_recovery_data *rec_data)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001287{
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001288 int status;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001289 struct kgsl_device *device = rb->device;
Shubhraprakash Dasadb16022012-05-31 16:19:37 -06001290 unsigned int rb_rptr = rb->wptr * sizeof(unsigned int);
Carter Cooper7e7f02e2012-02-15 09:36:31 -07001291 struct kgsl_context *context;
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001292 struct adreno_context *adreno_context;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001293
Shubhraprakash Dasadb16022012-05-31 16:19:37 -06001294 context = idr_find(&device->context_idr, rec_data->context_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001295
Shubhraprakash Das6f6ecb32012-06-13 12:17:11 -06001296 /* Look for the command stream that is right after the global eop */
1297 status = _find_cmd_seq_after_eop_ts(rb, &rb_rptr,
1298 rec_data->global_eop + 1, false);
Shubhraprakash Dasbb7b32a2012-06-04 15:36:39 -06001299 if (status)
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001300 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001301
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001302 if (context) {
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001303 adreno_context = context->devctxt;
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001304
1305 if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
1306 if (rec_data->ib1) {
1307 status = _find_hanging_ib_sequence(rb, &rb_rptr,
1308 rec_data->ib1);
1309 if (status)
1310 goto copy_rb_contents;
1311 }
1312 _turn_preamble_on_for_ib_seq(rb, rb_rptr);
Shubhraprakash Das32240ef2012-06-06 20:27:46 -06001313 } else {
1314 status = -EINVAL;
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001315 }
1316 }
1317
1318copy_rb_contents:
Shubhraprakash Das1d577fe2012-05-31 18:28:22 -06001319 _copy_valid_rb_content(rb, rb_rptr, rec_data->rb_buffer,
1320 &rec_data->rb_size,
1321 rec_data->bad_rb_buffer,
1322 &rec_data->bad_rb_size,
1323 &rec_data->last_valid_ctx_id);
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001324 /* If we failed to get the hanging IB sequence then we cannot execute
Shubhraprakash Das32240ef2012-06-06 20:27:46 -06001325 * commands from the bad context or preambles not supported */
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001326 if (status) {
1327 rec_data->bad_rb_size = 0;
1328 status = 0;
1329 }
Shubhraprakash Das32240ef2012-06-06 20:27:46 -06001330 /* If there is no context then that means there are no commands for
1331 * good case */
1332 if (!context)
1333 rec_data->rb_size = 0;
Shubhraprakash Das2a85f1f2012-06-04 17:01:39 -06001334done:
1335 return status;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001336}
1337
1338void
1339adreno_ringbuffer_restore(struct adreno_ringbuffer *rb, unsigned int *rb_buff,
1340 int num_rb_contents)
1341{
1342 int i;
1343 unsigned int *ringcmds;
1344 unsigned int rcmd_gpu;
1345
1346 if (!num_rb_contents)
1347 return;
1348
1349 if (num_rb_contents > (rb->buffer_desc.size - rb->wptr)) {
1350 adreno_regwrite(rb->device, REG_CP_RB_RPTR, 0);
1351 rb->rptr = 0;
1352 BUG_ON(num_rb_contents > rb->buffer_desc.size);
1353 }
1354 ringcmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
1355 rcmd_gpu = rb->buffer_desc.gpuaddr + sizeof(unsigned int) * rb->wptr;
1356 for (i = 0; i < num_rb_contents; i++)
1357 GSL_RB_WRITE(ringcmds, rcmd_gpu, rb_buff[i]);
1358 rb->wptr += num_rb_contents;
1359 adreno_ringbuffer_submit(rb);
1360}