static irqreturn_t z180_irq_handler(struct kgsl_device *device) { irqreturn_t result = IRQ_NONE; unsigned int status; struct z180_device *z180_dev = Z180_DEVICE(device); z180_regread(device, ADDR_VGC_IRQSTATUS >> 2, &status); trace_kgsl_z180_irq_status(device, status); if (status & GSL_VGC_INT_MASK) { z180_regwrite(device, ADDR_VGC_IRQSTATUS >> 2, status & GSL_VGC_INT_MASK); result = IRQ_HANDLED; if (status & REG_VGC_IRQSTATUS__FIFO_MASK) KGSL_DRV_ERR(device, "z180 fifo interrupt\n"); if (status & REG_VGC_IRQSTATUS__MH_MASK) kgsl_mh_intrcallback(device); if (status & REG_VGC_IRQSTATUS__G2D_MASK) { int count; z180_regread(device, ADDR_VGC_IRQ_ACTIVE_CNT >> 2, &count); count >>= 8; count &= 255; z180_dev->timestamp += count; queue_work(device->work_queue, &device->ts_expired_ws); wake_up_interruptible(&device->wait_queue); }
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); } }
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); z180_dump_ringbuffer(device); z180_dump_regs(device); if (device->pm_ib_enabled) z180_dump_ib(device); if (!manual) BUG_ON(1); return 0; }
/** * 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; }
static irqreturn_t z180_isr(int irq, void *data) { irqreturn_t result = IRQ_NONE; unsigned int status; struct kgsl_device *device = (struct kgsl_device *) data; struct z180_device *z180_dev = Z180_DEVICE(device); z180_regread(device, ADDR_VGC_IRQSTATUS >> 2, &status); if (status & GSL_VGC_INT_MASK) { z180_regwrite(device, ADDR_VGC_IRQSTATUS >> 2, status & GSL_VGC_INT_MASK); result = IRQ_HANDLED; if (status & REG_VGC_IRQSTATUS__FIFO_MASK) KGSL_DRV_ERR(device, "z180 fifo interrupt\n"); if (status & REG_VGC_IRQSTATUS__MH_MASK) kgsl_mh_intrcallback(device); if (status & REG_VGC_IRQSTATUS__G2D_MASK) { int count; z180_regread(device, ADDR_VGC_IRQ_ACTIVE_CNT >> 2, &count); count >>= 8; count &= 255; z180_dev->timestamp += count; queue_work(device->work_queue, &device->ts_expired_ws); wake_up_interruptible(&device->wait_queue); atomic_notifier_call_chain( &(device->ts_notifier_list), device->id, NULL); }
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); 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); } } }