void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb, struct adreno_submit_time *time) { struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); BUG_ON(rb->wptr == 0); /* Let the pwrscale policy know that new commands have been submitted. */ kgsl_pwrscale_busy(rb->device); /* Write the changes to CFF if so enabled */ _cff_write_ringbuffer(rb); /* * Read the current GPU ticks and wallclock for most accurate * profiling */ if (time != NULL) { /* * Here we are attempting to create a mapping between the * GPU time domain (alwayson counter) and the CPU time domain * (local_clock) by sampling both values as close together as * possible. This is useful for many types of debugging and * profiling. In order to make this mapping as accurate as * possible, we must turn off interrupts to avoid running * interrupt handlers between the two samples. */ unsigned long flags; local_irq_save(flags); if (gpudev->alwayson_counter_read != NULL) time->ticks = gpudev->alwayson_counter_read(adreno_dev); else time->ticks = 0; /* Get the kernel clock for time since boot */ time->ktime = local_clock(); /* Get the timeofday for the wall time (for the user) */ getnstimeofday(&time->utime); local_irq_restore(flags); } /* Memory barrier before informing the hardware of new commands */ mb(); adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_WPTR, rb->wptr); }
void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb, struct adreno_submit_time *time) { struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); BUG_ON(rb->wptr == 0); _cff_write_ringbuffer(rb); if (time != NULL) { unsigned long flags; local_irq_save(flags); if (!adreno_is_a3xx(adreno_dev)) { adreno_readreg64(adreno_dev, ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO, ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI, &time->ticks); if (ADRENO_GPUREV(adreno_dev) >= 400 && ADRENO_GPUREV(adreno_dev) <= ADRENO_REV_A530) time->ticks &= 0xFFFFFFFF; } else time->ticks = 0; time->ktime = local_clock(); getnstimeofday(&time->utime); local_irq_restore(flags); } mb(); if (adreno_preempt_state(adreno_dev, ADRENO_DISPATCHER_PREEMPT_CLEAR) && (adreno_dev->cur_rb == rb)) { kgsl_pwrscale_busy(rb->device); adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_WPTR, rb->wptr); } }