}
 
                ring->cur = ring->start;
+               ring->next = ring->start;
 
                /* reset completed fence seqno: */
                ring->memptrs->fence = ring->seqno;
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
        uint32_t wptr;
 
+       /* Copy the shadow to the actual register */
+       ring->cur = ring->next;
+
        /*
         * Mask wptr value that we calculate to fit in the HW range. This is
         * to account for the possibility that the last command fit exactly into
         * the ringbuffer and rb->next hasn't wrapped to zero yet
         */
-       wptr = get_wptr(ring) % (MSM_GPU_RINGBUFFER_SZ >> 2);
+       wptr = (ring->cur - ring->start) % (MSM_GPU_RINGBUFFER_SZ >> 2);
 
        /* ensure writes to ringbuffer have hit system memory: */
        mb();
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(ring->gpu);
        uint32_t size = MSM_GPU_RINGBUFFER_SZ >> 2;
-       uint32_t wptr = get_wptr(ring);
+       /* Use ring->next to calculate free size */
+       uint32_t wptr = ring->next - ring->start;
        uint32_t rptr = get_rptr(adreno_gpu, ring);
        return (rptr + (size - 1) - wptr) % size;
 }
 
        struct msm_gpu *gpu;
        int id;
        struct drm_gem_object *bo;
-       uint32_t *start, *end, *cur;
+       uint32_t *start, *end, *cur, *next;
        struct list_head submits;
        uint64_t iova;
        uint32_t seqno;
 static inline void
 OUT_RING(struct msm_ringbuffer *ring, uint32_t data)
 {
-       if (ring->cur == ring->end)
-               ring->cur = ring->start;
-       *(ring->cur++) = data;
+       /*
+        * ring->next points to the current command being written - it won't be
+        * committed as ring->cur until the flush
+        */
+       if (ring->next == ring->end)
+               ring->next = ring->start;
+       *(ring->next++) = data;
 }
 
 #endif /* __MSM_RINGBUFFER_H__ */