123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /* Copyright (c) 2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #include "kgsl.h"
- #include "kgsl_device.h"
- #include "z180.h"
- #include "z180_reg.h"
- #define Z180_STREAM_PACKET_CALL 0x7C000275
- /* Postmortem Dump formatted Output parameters */
- /* Number of Words per dump data line */
- #define WORDS_PER_LINE 8
- /* Number of spaces per dump data line */
- #define NUM_SPACES (WORDS_PER_LINE - 1)
- /*
- * Output dump data is formatted as string, hence number of chars
- * per line for line string allocation
- */
- #define CHARS_PER_LINE \
- ((WORDS_PER_LINE * (2*sizeof(unsigned int))) + NUM_SPACES + 1)
- /* Z180 registers (byte offsets) to be dumped */
- static const unsigned int regs_to_dump[] = {
- ADDR_VGC_VERSION,
- ADDR_VGC_SYSSTATUS,
- ADDR_VGC_IRQSTATUS,
- ADDR_VGC_IRQENABLE,
- ADDR_VGC_IRQ_ACTIVE_CNT,
- ADDR_VGC_CLOCKEN,
- ADDR_VGC_MH_DATA_ADDR,
- ADDR_VGC_GPR0,
- ADDR_VGC_GPR1,
- ADDR_VGC_BUSYCNT,
- ADDR_VGC_FIFOFREE,
- };
- /**
- * z180_dump_regs - Dumps all of Z180 external registers. Prints the word offset
- * of the register in each output line.
- * @device: kgsl_device pointer to the Z180 core
- */
- static void z180_dump_regs(struct kgsl_device *device)
- {
- unsigned int i;
- unsigned int reg_val;
- z180_idle(device);
- KGSL_LOG_DUMP(device, "Z180 Register Dump\n");
- for (i = 0; i < ARRAY_SIZE(regs_to_dump); i++) {
- kgsl_regread(device,
- regs_to_dump[i]/sizeof(unsigned int), ®_val);
- KGSL_LOG_DUMP(device, "REG: %04X: %08X\n",
- regs_to_dump[i]/sizeof(unsigned int), reg_val);
- }
- }
- /**
- * z180_dump_ringbuffer - Dumps the Z180 core's ringbuffer contents
- * @device: kgsl_device pointer to the z180 core
- */
- static void z180_dump_ringbuffer(struct kgsl_device *device)
- {
- unsigned int rb_size;
- unsigned int *rb_hostptr;
- unsigned int rb_words;
- unsigned int rb_gpuaddr;
- struct z180_device *z180_dev = Z180_DEVICE(device);
- unsigned int i;
- char linebuf[CHARS_PER_LINE];
- KGSL_LOG_DUMP(device, "Z180 ringbuffer dump\n");
- rb_hostptr = (unsigned int *) z180_dev->ringbuffer.cmdbufdesc.hostptr;
- rb_size = Z180_RB_SIZE;
- rb_gpuaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr;
- rb_words = rb_size/sizeof(unsigned int);
- KGSL_LOG_DUMP(device, "ringbuffer size: %u\n", rb_size);
- KGSL_LOG_DUMP(device, "rb_words: %d\n", rb_words);
- for (i = 0; i < rb_words; i += WORDS_PER_LINE) {
- hex_dump_to_buffer(rb_hostptr+i,
- rb_size - i*sizeof(unsigned int),
- WORDS_PER_LINE*sizeof(unsigned int),
- sizeof(unsigned int), linebuf,
- sizeof(linebuf), false);
- KGSL_LOG_DUMP(device, "RB: %04X: %s\n",
- rb_gpuaddr + i*sizeof(unsigned int), linebuf);
- }
- }
- static void z180_dump_ib(struct kgsl_device *device)
- {
- unsigned int rb_size;
- unsigned int *rb_hostptr;
- unsigned int rb_words;
- unsigned int rb_gpuaddr;
- unsigned int ib_gpuptr = 0;
- unsigned int ib_size = 0;
- void *ib_hostptr = NULL;
- int rb_slot_num = -1;
- struct z180_device *z180_dev = Z180_DEVICE(device);
- struct kgsl_mem_entry *entry = NULL;
- phys_addr_t pt_base;
- unsigned int i;
- unsigned int j;
- char linebuf[CHARS_PER_LINE];
- unsigned int current_ib_slot;
- unsigned int len;
- unsigned int rowsize;
- KGSL_LOG_DUMP(device, "Z180 IB dump\n");
- rb_hostptr = (unsigned int *) z180_dev->ringbuffer.cmdbufdesc.hostptr;
- rb_size = Z180_RB_SIZE;
- rb_gpuaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr;
- rb_words = rb_size/sizeof(unsigned int);
- KGSL_LOG_DUMP(device, "Ringbuffer size (bytes): %u\n", rb_size);
- KGSL_LOG_DUMP(device, "rb_words: %d\n", rb_words);
- pt_base = kgsl_mmu_get_current_ptbase(&device->mmu);
- /* Dump the current IB */
- for (i = 0; i < rb_words; i++) {
- if (rb_hostptr[i] == Z180_STREAM_PACKET_CALL) {
- rb_slot_num++;
- current_ib_slot =
- z180_dev->current_timestamp % Z180_PACKET_COUNT;
- if (rb_slot_num != current_ib_slot)
- continue;
- ib_gpuptr = rb_hostptr[i+1];
- entry = kgsl_get_mem_entry(device, pt_base, ib_gpuptr,
- 1);
- if (entry == NULL) {
- KGSL_LOG_DUMP(device,
- "IB mem entry not found for ringbuffer slot#: %d\n",
- rb_slot_num);
- continue;
- }
- ib_hostptr = kgsl_memdesc_map(&entry->memdesc);
- if (ib_hostptr == NULL) {
- KGSL_LOG_DUMP(device,
- "Could not map IB to kernel memory, Ringbuffer Slot: %d\n",
- rb_slot_num);
- kgsl_mem_entry_put(entry);
- continue;
- }
- ib_size = entry->memdesc.size;
- KGSL_LOG_DUMP(device,
- "IB size: %dbytes, IB size in words: %d\n",
- ib_size,
- ib_size/sizeof(unsigned int));
- for (j = 0; j < ib_size; j += WORDS_PER_LINE) {
- len = ib_size - j*sizeof(unsigned int);
- rowsize = WORDS_PER_LINE*sizeof(unsigned int);
- hex_dump_to_buffer(ib_hostptr+j, len, rowsize,
- sizeof(unsigned int), linebuf,
- sizeof(linebuf), false);
- KGSL_LOG_DUMP(device, "IB%d: %04X: %s\n",
- rb_slot_num,
- (rb_gpuaddr +
- j*sizeof(unsigned int)),
- linebuf);
- }
- KGSL_LOG_DUMP(device, "IB Dump Finished\n");
- kgsl_mem_entry_put(entry);
- }
- }
- }
- /**
- * z180_dump - Dumps the Z180 ringbuffer and registers (and IBs if asked for)
- * for postmortem
- * analysis.
- * @device: kgsl_device pointer to the Z180 core
- */
- int z180_dump(struct kgsl_device *device, int manual)
- {
- struct z180_device *z180_dev = Z180_DEVICE(device);
- mb();
- KGSL_LOG_DUMP(device, "Retired Timestamp: %d\n", z180_dev->timestamp);
- KGSL_LOG_DUMP(device,
- "Current Timestamp: %d\n", z180_dev->current_timestamp);
- /* Dump ringbuffer */
- z180_dump_ringbuffer(device);
- /* Dump registers */
- z180_dump_regs(device);
- /* Dump IBs, if asked for */
- if (device->pm_ib_enabled)
- z180_dump_ib(device);
- /* Get the stack trace if the dump was automatic */
- if (!manual)
- BUG_ON(1);
- return 0;
- }
|