int kgsl_g12_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, int drawctxt_index, uint32_t ibaddr, int sizedwords, uint32_t *timestamp, unsigned int ctrl) { unsigned int result = 0; unsigned int ofs = PACKETSIZE_STATESTREAM * sizeof(unsigned int); unsigned int cnt = 5; unsigned int nextaddr = 0; unsigned int index = 0; unsigned int nextcnt = 0x9000 | 5; struct kgsl_memdesc tmp = {0}; unsigned int cmd; struct kgsl_device *device = dev_priv->device; struct kgsl_pagetable *pagetable = dev_priv->process_priv->pagetable; struct kgsl_g12_device *g12_device = (struct kgsl_g12_device *) device; cmd = ibaddr; tmp.hostptr = (void *)*timestamp; KGSL_CMD_INFO("ctxt %d ibaddr 0x%08x sizedwords %d", drawctxt_index, ibaddr, sizedwords); if (drawctxt_index != (int)g_z1xx.prevctx) { kgsl_mmu_setstate(device, pagetable); cnt = PACKETSIZE_STATESTREAM; ofs = 0; } else { kgsl_g12_setstate(device, device->mmu.tlb_flags); } result = wait_event_interruptible_timeout(g12_device->wait_timestamp_wq, room_in_rb(g12_device), msecs_to_jiffies(KGSL_TIMEOUT_DEFAULT)); if (result < 0) { KGSL_CMD_ERR("failed waiting for ringbuffer. result %d", result); goto error; } result = 0; index = g12_device->current_timestamp % KGSL_G12_PACKET_COUNT; g12_device->current_timestamp++; *timestamp = g12_device->current_timestamp; g_z1xx.prevctx = drawctxt_index; addcmd(&g_z1xx, index, cmd + ofs, cnt); nextaddr = g_z1xx.cmdbufdesc.physaddr + rb_offset((index + 1) % KGSL_G12_PACKET_COUNT); tmp.hostptr = (void *)(tmp.hostptr + (sizedwords * sizeof(unsigned int))); tmp.size = 12; kgsl_sharedmem_writel(&tmp, 4, nextaddr); kgsl_sharedmem_writel(&tmp, 8, nextcnt); kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 1); kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); error: return result; }
int kgsl_g12_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, struct kgsl_context *context, struct kgsl_ibdesc *ibdesc, unsigned int numibs, uint32_t *timestamp, unsigned int ctrl) { int result = 0; unsigned int ofs = PACKETSIZE_STATESTREAM * sizeof(unsigned int); unsigned int cnt = 5; unsigned int nextaddr = 0; unsigned int index = 0; unsigned int nextindex; unsigned int nextcnt = KGSL_G12_STREAM_END_CMD | 5; struct kgsl_memdesc tmp = {0}; unsigned int cmd; struct kgsl_device *device = dev_priv->device; struct kgsl_pagetable *pagetable = dev_priv->process_priv->pagetable; struct kgsl_g12_device *g12_device = KGSL_G12_DEVICE(device); unsigned int sizedwords; if (device->state & KGSL_STATE_HUNG) { return -EINVAL; goto error; } if (numibs != 1) { KGSL_DRV_ERR(device, "Invalid number of ibs: %d\n", numibs); result = -EINVAL; goto error; } cmd = ibdesc[0].gpuaddr; sizedwords = ibdesc[0].sizedwords; tmp.hostptr = (void *)*timestamp; KGSL_CMD_INFO(device, "ctxt %d ibaddr 0x%08x sizedwords %d\n", context->id, cmd, sizedwords); /* context switch */ if ((context->id != (int)g12_device->ringbuffer.prevctx) || (ctrl & KGSL_CONTEXT_CTX_SWITCH)) { KGSL_CMD_INFO(device, "context switch %d -> %d\n", context->id, g12_device->ringbuffer.prevctx); kgsl_mmu_setstate(device, pagetable); cnt = PACKETSIZE_STATESTREAM; ofs = 0; } kgsl_g12_setstate(device, kgsl_pt_get_flags(device->mmu.hwpagetable, device->id)); result = wait_event_interruptible_timeout(device->wait_queue, room_in_rb(g12_device), msecs_to_jiffies(KGSL_TIMEOUT_DEFAULT)); if (result <= 0) { KGSL_CMD_ERR(device, "wait_event_interruptible_timeout " "failed: %d\n", result); goto error; } result = 0; index = g12_device->current_timestamp % KGSL_G12_PACKET_COUNT; g12_device->current_timestamp++; nextindex = g12_device->current_timestamp % KGSL_G12_PACKET_COUNT; *timestamp = g12_device->current_timestamp; g12_device->ringbuffer.prevctx = context->id; addcmd(&g12_device->ringbuffer, index, cmd + ofs, cnt); /* Make sure the next ringbuffer entry has a marker */ addmarker(&g12_device->ringbuffer, nextindex); nextaddr = g12_device->ringbuffer.cmdbufdesc.gpuaddr + rb_offset(nextindex); tmp.hostptr = (void *)(tmp.hostptr + (sizedwords * sizeof(unsigned int))); tmp.size = 12; kgsl_sharedmem_writel(&tmp, 4, nextaddr); kgsl_sharedmem_writel(&tmp, 8, nextcnt); /* sync memory before activating the hardware for the new command*/ mb(); cmd = (int)(((2) & VGV3_CONTROL_MARKADD_FMASK) << VGV3_CONTROL_MARKADD_FSHIFT); kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, cmd); kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); error: return result; }
int kgsl_g12_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, int drawctxt_index, uint32_t ibaddr, int sizedwords, uint32_t *timestamp, unsigned int ctrl) { unsigned int result = 0; unsigned int ofs = PACKETSIZE_STATESTREAM * sizeof(unsigned int); unsigned int cnt = 5; unsigned int nextaddr = 0; unsigned int index = 0; unsigned int nextindex; unsigned int nextcnt = KGSL_G12_STREAM_END_CMD | 5; struct kgsl_memdesc tmp = {0}; unsigned int cmd; struct kgsl_device *device = dev_priv->device; struct kgsl_pagetable *pagetable = dev_priv->process_priv->pagetable; struct kgsl_g12_device *g12_device = (struct kgsl_g12_device *) device; cmd = ibaddr; tmp.hostptr = (void *)*timestamp; KGSL_CMD_INFO("ctxt %d ibaddr 0x%08x sizedwords %d", drawctxt_index, ibaddr, sizedwords); /* context switch */ if (drawctxt_index != (int)g12_device->ringbuffer.prevctx) { KGSL_CMD_INFO("context switch %d -> %d", drawctxt_index, g12_device->ringbuffer.prevctx); kgsl_mmu_setstate(device, pagetable); cnt = PACKETSIZE_STATESTREAM; ofs = 0; } kgsl_g12_setstate(device, kgsl_pt_get_flags(device->mmu.hwpagetable, device->id)); result = wait_event_interruptible_timeout(g12_device->wait_timestamp_wq, room_in_rb(g12_device), msecs_to_jiffies(KGSL_TIMEOUT_DEFAULT)); if (result < 0) { KGSL_CMD_ERR("failed waiting for ringbuffer. result %d", result); goto error; } result = 0; index = g12_device->current_timestamp % KGSL_G12_PACKET_COUNT; g12_device->current_timestamp++; nextindex = g12_device->current_timestamp % KGSL_G12_PACKET_COUNT; *timestamp = g12_device->current_timestamp; g12_device->ringbuffer.prevctx = drawctxt_index; addcmd(&g12_device->ringbuffer, index, cmd + ofs, cnt); /* Make sure the next ringbuffer entry has a marker */ addmarker(&g12_device->ringbuffer, nextindex); nextaddr = g12_device->ringbuffer.cmdbufdesc.gpuaddr + rb_offset(nextindex); tmp.hostptr = (void *)(tmp.hostptr + (sizedwords * sizeof(unsigned int))); tmp.size = 12; kgsl_sharedmem_writel(&tmp, 4, nextaddr); kgsl_sharedmem_writel(&tmp, 8, nextcnt); cmd = (int)(((2) & VGV3_CONTROL_MARKADD_FMASK) << VGV3_CONTROL_MARKADD_FSHIFT); kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, cmd); kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); error: return result; }
/* functions */ void kgsl_cp_intrcallback(struct kgsl_device *device) { unsigned int status = 0, num_reads = 0, master_status = 0; struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(device); struct kgsl_ringbuffer *rb = &yamato_device->ringbuffer; kgsl_yamato_regread_isr(device, REG_MASTER_INT_SIGNAL, &master_status); while (!status && (num_reads < VALID_STATUS_COUNT_MAX) && (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) { kgsl_yamato_regread_isr(device, REG_CP_INT_STATUS, &status); kgsl_yamato_regread_isr(device, REG_MASTER_INT_SIGNAL, &master_status); num_reads++; } if (num_reads > 1) KGSL_DRV_WARN(device, "Looped %d times to read REG_CP_INT_STATUS\n", num_reads); if (!status) { if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) { /* This indicates that we could not read CP_INT_STAT. * As a precaution just wake up processes so * they can check their timestamps. Since, we * did not ack any interrupts this interrupt will * be generated again */ KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n"); wake_up_interruptible_all(&device->wait_queue); } else KGSL_DRV_WARN(device, "Spurious interrput detected\n"); return; } if (status & CP_INT_CNTL__RB_INT_MASK) { /* signal intr completion event */ unsigned int enableflag = 0; kgsl_sharedmem_writel(&rb->device->memstore, KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable), enableflag); wmb(); KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n"); } if (status & CP_INT_CNTL__T0_PACKET_IN_IB_MASK) { KGSL_CMD_CRIT(rb->device, "ringbuffer TO packet in IB interrupt\n"); kgsl_yamato_regwrite_isr(rb->device, REG_CP_INT_CNTL, 0); } if (status & CP_INT_CNTL__OPCODE_ERROR_MASK) { KGSL_CMD_CRIT(rb->device, "ringbuffer opcode error interrupt\n"); kgsl_yamato_regwrite_isr(rb->device, REG_CP_INT_CNTL, 0); } if (status & CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK) { KGSL_CMD_CRIT(rb->device, "ringbuffer protected mode error interrupt\n"); kgsl_yamato_regwrite_isr(rb->device, REG_CP_INT_CNTL, 0); } if (status & CP_INT_CNTL__RESERVED_BIT_ERROR_MASK) { KGSL_CMD_CRIT(rb->device, "ringbuffer reserved bit error interrupt\n"); kgsl_yamato_regwrite_isr(rb->device, REG_CP_INT_CNTL, 0); } if (status & CP_INT_CNTL__IB_ERROR_MASK) { KGSL_CMD_CRIT(rb->device, "ringbuffer IB error interrupt\n"); kgsl_yamato_regwrite_isr(rb->device, REG_CP_INT_CNTL, 0); } if (status & CP_INT_CNTL__SW_INT_MASK) KGSL_CMD_INFO(rb->device, "ringbuffer software interrupt\n"); if (status & CP_INT_CNTL__IB2_INT_MASK) KGSL_CMD_INFO(rb->device, "ringbuffer ib2 interrupt\n"); if (status & (~GSL_CP_INT_MASK)) KGSL_CMD_WARN(rb->device, "bad bits in REG_CP_INT_STATUS %08x\n", status); /* only ack bits we understand */ status &= GSL_CP_INT_MASK; kgsl_yamato_regwrite_isr(device, REG_CP_INT_ACK, status); if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) { KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n"); wake_up_interruptible_all(&device->wait_queue); atomic_notifier_call_chain(&(device->ts_notifier_list), KGSL_DEVICE_YAMATO, NULL); } }