static int adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, unsigned int numcmds, int wptr_ahead) { int nopcount; unsigned int freecmds; unsigned int *cmds; unsigned int gpuaddr; unsigned long wait_time; unsigned long wait_timeout = msecs_to_jiffies(ADRENO_IDLE_TIMEOUT); unsigned long wait_time_part; unsigned int rptr; /* if wptr ahead, fill the remaining with NOPs */ if (wptr_ahead) { /* -1 for header */ nopcount = KGSL_RB_DWORDS - rb->wptr - 1; cmds = RB_HOSTPTR(rb, rb->wptr); gpuaddr = RB_GPUADDR(rb, rb->wptr); *cmds = cp_nop_packet(nopcount); kgsl_cffdump_write(rb->device, gpuaddr, *cmds); /* 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 { rptr = adreno_get_rptr(rb); } while (!rptr); 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) { rptr = adreno_get_rptr(rb); freecmds = 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", rptr, rb->wptr); return -ETIMEDOUT; } } return 0; }
unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb, unsigned int numcmds) { unsigned int *ptr = NULL; int ret = 0; unsigned int rptr; BUG_ON(numcmds >= KGSL_RB_DWORDS); rptr = adreno_get_rptr(rb); /* check for available space */ if (rb->wptr >= rptr) { /* wptr ahead or equal to rptr */ /* reserve dwords for nop packet */ if ((rb->wptr + numcmds) > (KGSL_RB_DWORDS - GSL_RB_NOP_SIZEDWORDS)) ret = adreno_ringbuffer_waitspace(rb, numcmds, 1); } else { /* wptr behind rptr */ if ((rb->wptr + numcmds) >= rptr) ret = adreno_ringbuffer_waitspace(rb, numcmds, 0); /* check for remaining space */ /* reserve dwords for nop packet */ if (!ret && (rb->wptr + numcmds) > (KGSL_RB_DWORDS - GSL_RB_NOP_SIZEDWORDS)) ret = adreno_ringbuffer_waitspace(rb, numcmds, 1); } if (!ret) { rb->last_wptr = rb->wptr; ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; rb->wptr += numcmds; } else ptr = ERR_PTR(ret); return ptr; }
unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb, unsigned int numcmds) { unsigned int *ptr = NULL; int ret = 0; unsigned int rptr; BUG_ON(numcmds >= KGSL_RB_DWORDS); rptr = adreno_get_rptr(rb); if (rb->wptr >= rptr) { if ((rb->wptr + numcmds) > (KGSL_RB_DWORDS - GSL_RB_NOP_SIZEDWORDS)) ret = adreno_ringbuffer_waitspace(rb, numcmds, 1); } else { if ((rb->wptr + numcmds) >= rptr) ret = adreno_ringbuffer_waitspace(rb, numcmds, 0); if (!ret && (rb->wptr + numcmds) > (KGSL_RB_DWORDS - GSL_RB_NOP_SIZEDWORDS)) ret = adreno_ringbuffer_waitspace(rb, numcmds, 1); } if (!ret) { rb->last_wptr = rb->wptr; ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; rb->wptr += numcmds; } else ptr = ERR_PTR(ret); return ptr; }
static int adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, unsigned int numcmds, int wptr_ahead) { int nopcount = 0; unsigned int freecmds; unsigned int wptr = rb->wptr; unsigned int *cmds = NULL; uint64_t gpuaddr; unsigned long wait_time; unsigned long wait_timeout = msecs_to_jiffies(ADRENO_IDLE_TIMEOUT); unsigned int rptr; struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); if (wptr_ahead) { nopcount = KGSL_RB_DWORDS - rb->wptr - 1; cmds = RB_HOSTPTR(rb, rb->wptr); gpuaddr = RB_GPUADDR(rb, rb->wptr); rptr = adreno_get_rptr(rb); if ((adreno_dev->cur_rb != rb || !adreno_preempt_state(adreno_dev, ADRENO_DISPATCHER_PREEMPT_CLEAR)) && !rptr) return -ENOSPC; wait_time = jiffies + wait_timeout; while (!rptr) { rptr = adreno_get_rptr(rb); if (time_after(jiffies, wait_time)) return -ETIMEDOUT; } rb->wptr = 0; } rptr = adreno_get_rptr(rb); freecmds = rptr - rb->wptr; if (freecmds == 0 || freecmds > numcmds) goto done; if (adreno_dev->cur_rb != rb || !adreno_preempt_state(adreno_dev, ADRENO_DISPATCHER_PREEMPT_CLEAR)) { rb->wptr = wptr; return -ENOSPC; } wait_time = jiffies + wait_timeout; while (1) { rptr = adreno_get_rptr(rb); freecmds = rptr - rb->wptr; if (freecmds == 0 || freecmds > numcmds) break; if (time_after(jiffies, wait_time)) { KGSL_DRV_ERR(rb->device, "Timed out waiting for freespace in RB rptr: 0x%x, wptr: 0x%x, rb id %d\n", rptr, wptr, rb->id); return -ETIMEDOUT; } } done: if (wptr_ahead) { *cmds = cp_packet(adreno_dev, CP_NOP, nopcount); kgsl_cffdump_write(rb->device, gpuaddr, *cmds); } return 0; }