static void adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, unsigned int numcmds, int wptr_ahead) { int nopcount; unsigned int freecmds; unsigned int *cmds; uint cmds_gpu; struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); unsigned long wait_timeout = msecs_to_jiffies(adreno_dev->wait_timeout); unsigned long wait_time; /* if wptr ahead, fill the remaining with NOPs */ if (wptr_ahead) { /* -1 for header */ nopcount = rb->sizedwords - rb->wptr - 1; cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*rb->wptr; GSL_RB_WRITE(cmds, cmds_gpu, cp_nop_packet(nopcount)); /* Make sure that rptr is not 0 before submitting * commands at the end of ringbuffer. We do not * want the rptr and wptr to become equal when * the ringbuffer is not empty */ do { GSL_RB_GET_READPTR(rb, &rb->rptr); } while (!rb->rptr); rb->wptr++; adreno_ringbuffer_submit(rb); rb->wptr = 0; } wait_time = jiffies + wait_timeout; /* wait for space in ringbuffer */ while (1) { GSL_RB_GET_READPTR(rb, &rb->rptr); freecmds = rb->rptr - rb->wptr; if (freecmds == 0 || freecmds > numcmds) break; if (time_after(jiffies, wait_time)) { KGSL_DRV_ERR(rb->device, "Timed out while waiting for freespace in ringbuffer " "rptr: 0x%x, wptr: 0x%x\n", rb->rptr, rb->wptr); if (!adreno_dump_and_recover(rb->device)) wait_time = jiffies + wait_timeout; else /* GPU is hung and we cannot recover */ BUG(); } } }
static int kgsl_ringbuffer_waitspace(struct kgsl_ringbuffer *rb, unsigned int numcmds, int wptr_ahead) { int nopcount; unsigned int freecmds; unsigned int *cmds; uint cmds_gpu; KGSL_CMD_VDBG("enter (rb=%p, numcmds=%d, wptr_ahead=%d)\n", rb, numcmds, wptr_ahead); /* if wptr ahead, fill the remaining with NOPs */ if (wptr_ahead) { /* -1 for header */ nopcount = rb->sizedwords - rb->wptr - 1; cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*rb->wptr; GSL_RB_WRITE(cmds, cmds_gpu, pm4_nop_packet(nopcount)); /* Make sure that rptr is not 0 before submitting * commands at the end of ringbuffer. We do not * want the rptr and wptr to become equal when * the ringbuffer is not empty */ do { GSL_RB_GET_READPTR(rb, &rb->rptr); } while (!rb->rptr); rb->wptr++; kgsl_ringbuffer_submit(rb); rb->wptr = 0; } /* wait for space in ringbuffer */ do { GSL_RB_GET_READPTR(rb, &rb->rptr); freecmds = rb->rptr - rb->wptr; } while ((freecmds != 0) && (freecmds <= numcmds)); KGSL_CMD_VDBG("return %d\n", 0); return 0; }
unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb, unsigned int numcmds) { unsigned int *ptr = NULL; BUG_ON(numcmds >= rb->sizedwords); GSL_RB_GET_READPTR(rb, &rb->rptr); /* check for available space */ if (rb->wptr >= rb->rptr) { /* wptr ahead or equal to rptr */ /* reserve dwords for nop packet */ if ((rb->wptr + numcmds) > (rb->sizedwords - GSL_RB_NOP_SIZEDWORDS)) adreno_ringbuffer_waitspace(rb, numcmds, 1); } else { /* wptr behind rptr */ if ((rb->wptr + numcmds) >= rb->rptr) adreno_ringbuffer_waitspace(rb, numcmds, 0); /* check for remaining space */ /* reserve dwords for nop packet */ if ((rb->wptr + numcmds) > (rb->sizedwords - GSL_RB_NOP_SIZEDWORDS)) adreno_ringbuffer_waitspace(rb, numcmds, 1); } ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; rb->wptr += numcmds; return ptr; }
unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb, unsigned int numcmds) { unsigned int *ptr = NULL; BUG_ON(numcmds >= rb->sizedwords); GSL_RB_GET_READPTR(rb, &rb->rptr); if (rb->wptr >= rb->rptr) { if ((rb->wptr + numcmds) > (rb->sizedwords - GSL_RB_NOP_SIZEDWORDS)) adreno_ringbuffer_waitspace(rb, numcmds, 1); } else { if ((rb->wptr + numcmds) >= rb->rptr) adreno_ringbuffer_waitspace(rb, numcmds, 0); if ((rb->wptr + numcmds) > (rb->sizedwords - GSL_RB_NOP_SIZEDWORDS)) adreno_ringbuffer_waitspace(rb, numcmds, 1); } ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; rb->wptr += numcmds; return ptr; }
void kgsl_ringbuffer_watchdog() { struct kgsl_device *device = NULL; struct kgsl_ringbuffer *rb = NULL; device = &kgsl_driver.yamato_device; BUG_ON(device == NULL); rb = &device->ringbuffer; KGSL_CMD_VDBG("enter\n"); if ((rb->flags & KGSL_FLAGS_STARTED) == 0) { KGSL_CMD_VDBG("not started\n"); return; } GSL_RB_GET_READPTR(rb, &rb->rptr); if (rb->rptr == rb->wptr) { /* clear rptr sample for interval n */ rb->watchdog.flags &= ~KGSL_FLAGS_ACTIVE; goto done; } /* ringbuffer is currently not empty */ /* and a rptr sample was taken during interval n-1 */ if (rb->watchdog.flags & KGSL_FLAGS_ACTIVE) { /* and the rptr did not advance between * interval n-1 and n */ if (rb->rptr == rb->watchdog.rptr_sample) { /* then the core has hung */ KGSL_CMD_FATAL("Watchdog detected core hung.\n"); goto done; } /* save rptr sample for interval n */ rb->watchdog.flags |= KGSL_FLAGS_ACTIVE; rb->watchdog.rptr_sample = rb->rptr; } done: KGSL_CMD_VDBG("return\n"); }
void kgsl_ringbuffer_watchdog(struct kgsl_device *device) { struct kgsl_ringbuffer *rb = NULL; BUG_ON(device == NULL); rb = &device->ringbuffer; KGSL_CMD_VDBG("enter\n"); if ((rb->flags & KGSL_FLAGS_STARTED) == 0) { KGSL_CMD_VDBG("not started\n"); return; } GSL_RB_GET_READPTR(rb, &rb->rptr); if (rb->rptr == rb->wptr) { rb->watchdog.flags &= ~KGSL_FLAGS_ACTIVE; goto done; } if (rb->watchdog.flags & KGSL_FLAGS_ACTIVE) { if (rb->rptr == rb->watchdog.rptr_sample) { KGSL_CMD_FATAL("Watchdog detected core hung.\n"); goto done; } rb->watchdog.flags |= KGSL_FLAGS_ACTIVE; rb->watchdog.rptr_sample = rb->rptr; } done: KGSL_CMD_VDBG("return\n"); }
static int kgsl_ringbuffer_waitspace(struct kgsl_ringbuffer *rb, unsigned int numcmds, int wptr_ahead) { int nopcount; unsigned int freecmds; unsigned int *cmds; KGSL_CMD_VDBG("enter (rb=%p, numcmds=%d, wptr_ahead=%d)\n", rb, numcmds, wptr_ahead); if (wptr_ahead) { nopcount = rb->sizedwords - rb->wptr - 1; cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; GSL_RB_WRITE(cmds, pm4_nop_packet(nopcount)); rb->wptr++; kgsl_ringbuffer_submit(rb); rb->wptr = 0; } do { GSL_RB_GET_READPTR(rb, &rb->rptr); freecmds = rb->rptr - rb->wptr; } while ((freecmds != 0) && (freecmds < numcmds)); KGSL_CMD_VDBG("return %d\n", 0); return 0; }
static void adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, unsigned int numcmds, int wptr_ahead) { int nopcount; unsigned int freecmds; unsigned int *cmds; uint cmds_gpu; unsigned long wait_time; unsigned long wait_timeout = msecs_to_jiffies(ADRENO_IDLE_TIMEOUT); unsigned long wait_time_part; unsigned int prev_reg_val[hang_detect_regs_count]; memset(prev_reg_val, 0, sizeof(prev_reg_val)); /* if wptr ahead, fill the remaining with NOPs */ if (wptr_ahead) { /* -1 for header */ nopcount = rb->sizedwords - rb->wptr - 1; cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*rb->wptr; GSL_RB_WRITE(cmds, cmds_gpu, cp_nop_packet(nopcount)); /* Make sure that rptr is not 0 before submitting * commands at the end of ringbuffer. We do not * want the rptr and wptr to become equal when * the ringbuffer is not empty */ do { GSL_RB_GET_READPTR(rb, &rb->rptr); } while (!rb->rptr); rb->wptr++; adreno_ringbuffer_submit(rb); rb->wptr = 0; } wait_time = jiffies + wait_timeout; wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART); /* wait for space in ringbuffer */ while (1) { GSL_RB_GET_READPTR(rb, &rb->rptr); freecmds = rb->rptr - rb->wptr; if (freecmds == 0 || freecmds > numcmds) break; /* Dont wait for timeout, detect hang faster. */ if (time_after(jiffies, wait_time_part)) { wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART); if ((adreno_hang_detect(rb->device, prev_reg_val))){ KGSL_DRV_ERR(rb->device, "Hang detected while waiting for freespace in" "ringbuffer rptr: 0x%x, wptr: 0x%x\n", rb->rptr, rb->wptr); goto err; } } if (time_after(jiffies, wait_time)) { KGSL_DRV_ERR(rb->device, "Timed out while waiting for freespace in ringbuffer " "rptr: 0x%x, wptr: 0x%x\n", rb->rptr, rb->wptr); goto err; } continue; err: if (!adreno_dump_and_recover(rb->device)) wait_time = jiffies + wait_timeout; else /* GPU is hung and we cannot recover */ BUG(); } }
static void adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, unsigned int numcmds, int wptr_ahead) { int nopcount; unsigned int freecmds; unsigned int *cmds; uint cmds_gpu; struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); unsigned long wait_timeout = msecs_to_jiffies(adreno_dev->wait_timeout); unsigned long wait_time; unsigned long wait_time_part; unsigned int msecs_part = KGSL_TIMEOUT_PART; unsigned int prev_reg_val[hang_detect_regs_count]; memset(prev_reg_val, 0, sizeof(prev_reg_val)); if (wptr_ahead) { nopcount = rb->sizedwords - rb->wptr - 1; cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*rb->wptr; GSL_RB_WRITE(cmds, cmds_gpu, cp_nop_packet(nopcount)); do { GSL_RB_GET_READPTR(rb, &rb->rptr); } while (!rb->rptr); rb->wptr++; adreno_ringbuffer_submit(rb); rb->wptr = 0; } wait_time = jiffies + wait_timeout; wait_time_part = jiffies + msecs_to_jiffies(msecs_part); while (1) { GSL_RB_GET_READPTR(rb, &rb->rptr); freecmds = rb->rptr - rb->wptr; if (freecmds == 0 || freecmds > numcmds) break; if (time_after(jiffies, wait_time_part)) { wait_time_part = jiffies + msecs_to_jiffies(msecs_part); if ((adreno_hang_detect(rb->device, prev_reg_val))){ KGSL_DRV_ERR(rb->device, "Hang detected while waiting for freespace in" "ringbuffer rptr: 0x%x, wptr: 0x%x\n", rb->rptr, rb->wptr); goto err; } } if (time_after(jiffies, wait_time)) { KGSL_DRV_ERR(rb->device, "Timed out while waiting for freespace in ringbuffer " "rptr: 0x%x, wptr: 0x%x\n", rb->rptr, rb->wptr); goto err; } continue; err: if (!adreno_dump_and_recover(rb->device)) { wait_time = jiffies + wait_timeout; } else { BUG(); } } }