コード例 #1
0
/**
 * adreno_context_restore() - generic context restore handler
 * @adreno_dev: the device
 * @context: the context
 *
 * Basic context restore handler that writes the context identifier
 * to the ringbuffer and issues pagetable switch commands if necessary.
 */
static int adreno_context_restore(struct adreno_device *adreno_dev,
				  struct adreno_context *context)
{
	struct kgsl_device *device;
	unsigned int cmds[8];

	if (adreno_dev == NULL || context == NULL)
		return -EINVAL;

	device = &adreno_dev->dev;

	/* write the context identifier to the ringbuffer */
	cmds[0] = cp_nop_packet(1);
	cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
	cmds[3] = device->memstore.gpuaddr +
		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
	cmds[4] = context->base.id;
	/* Flush the UCHE for new context */
	cmds[5] = cp_type0_packet(
		adreno_getreg(adreno_dev, ADRENO_REG_UCHE_INVALIDATE0), 2);
	cmds[6] = 0;
	if (adreno_is_a4xx(adreno_dev))
		cmds[7] = 0x12;
	else if (adreno_is_a3xx(adreno_dev))
		cmds[7] = 0x90000000;
	return adreno_ringbuffer_issuecmds(device, context,
				KGSL_CMD_FLAGS_NONE, cmds, 8);
}
コード例 #2
0
static void _snapshot_hlsq_regs(struct kgsl_snapshot_registers *regs,
	struct kgsl_snapshot_registers_list *list,
	struct adreno_device *adreno_dev)
{
	
	if (!adreno_is_a3xx(adreno_dev)) {
		regs[list->count].regs = (unsigned int *) a3xx_hlsq_registers;
		regs[list->count].count = a3xx_hlsq_registers_count;
		list->count++;
	}
}
コード例 #3
0
/**
 * adreno_context_restore() - generic context restore handler
 * @rb: The RB in which context is to be restored
 *
 * Basic context restore handler that writes the context identifier
 * to the ringbuffer and issues pagetable switch commands if necessary.
 */
static void adreno_context_restore(struct adreno_ringbuffer *rb)
{
	struct kgsl_device *device = rb->device;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_context *drawctxt = rb->drawctxt_active;
	unsigned int cmds[11];
	int ret;

	if (!drawctxt)
		return;
	/*
	 * write the context identifier to the ringbuffer, write to both
	 * the global index and the index of the RB in which the context
	 * operates. The global values will always be reliable since we
	 * could be in middle of RB switch in which case the RB value may
	 * not be accurate
	 */
	cmds[0] = cp_nop_packet(1);
	cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
	cmds[3] = device->memstore.gpuaddr +
		KGSL_MEMSTORE_RB_OFFSET(rb, current_context);
	cmds[4] = drawctxt->base.id;
	cmds[5] = cp_type3_packet(CP_MEM_WRITE, 2);
	cmds[6] = device->memstore.gpuaddr +
		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
					current_context);
	cmds[7] = drawctxt->base.id;
	/* Flush the UCHE for new context */
	cmds[8] = cp_type0_packet(
		adreno_getreg(adreno_dev, ADRENO_REG_UCHE_INVALIDATE0), 2);
	cmds[9] = 0;
	if (adreno_is_a4xx(adreno_dev))
		cmds[10] = 0x12;
	else if (adreno_is_a3xx(adreno_dev))
		cmds[10] = 0x90000000;
	ret = adreno_ringbuffer_issuecmds(rb, KGSL_CMD_FLAGS_NONE, cmds, 11);
	if (ret) {
		/*
		 * A failure to submit commands to ringbuffer means RB may
		 * be full, in this case wait for idle and use CPU
		 */
		ret = adreno_idle(device);
		BUG_ON(ret);
		_adreno_context_restore_cpu(rb, drawctxt);
	}
}
コード例 #4
0
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);
	}
}
コード例 #5
0
int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	int i;

	if (adreno_dev->pm4_fw == NULL) {
		int ret = adreno_ringbuffer_read_pm4_ucode(device);
		if (ret)
			return ret;
	}

	KGSL_DRV_INFO(device, "loading pm4 ucode version: %d\n",
		adreno_dev->pm4_fw_version);
	if (adreno_is_a3xx(adreno_dev))
		adreno_regwrite(device, REG_CP_DEBUG, CP_DEBUG_DEFAULT);
	else
		adreno_regwrite(device, REG_CP_DEBUG, 0x02000000);
	adreno_regwrite(device, REG_CP_ME_RAM_WADDR, 0);
	for (i = 1; i < adreno_dev->pm4_fw_size; i++)
		adreno_regwrite(device, REG_CP_ME_RAM_DATA,
				adreno_dev->pm4_fw[i]);

	return 0;
}
コード例 #6
0
static uint32_t
adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
                          struct adreno_context *context,
                          unsigned int flags, unsigned int *cmds,
                          int sizedwords)
{
    struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
    unsigned int *ringcmds;
    unsigned int timestamp;
    unsigned int total_sizedwords = sizedwords;
    unsigned int i;
    unsigned int rcmd_gpu;
    unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
    unsigned int gpuaddr = rb->device->memstore.gpuaddr;

    if (context != NULL) {
        /*
         * if the context was not created with per context timestamp
         * support, we must use the global timestamp since issueibcmds
         * will be returning that one.
         */
        if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)
            context_id = context->id;
    }

    /* reserve space to temporarily turn off protected mode
    *  error checking if needed
    */
    total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
    total_sizedwords += !(flags & KGSL_CMD_FLAGS_NO_TS_CMP) ? 7 : 0;
    total_sizedwords += !(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD) ? 2 : 0;

    if (adreno_is_a3xx(adreno_dev))
        total_sizedwords += 7;

    total_sizedwords += 2; /* scratchpad ts for recovery */
    if (context) {
        total_sizedwords += 3; /* sop timestamp */
        total_sizedwords += 4; /* eop timestamp */
        total_sizedwords += 3; /* global timestamp without cache
					* flush for non-zero context */
    } else {
        total_sizedwords += 4; /* global timestamp for recovery*/
    }

    ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords);
    rcmd_gpu = rb->buffer_desc.gpuaddr
               + sizeof(uint)*(rb->wptr-total_sizedwords);

    if (!(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD)) {
        GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
    }
    if (flags & KGSL_CMD_FLAGS_PMODE) {
        /* disable protected mode error checking */
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
    }

    for (i = 0; i < sizedwords; i++) {
        GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds);
        cmds++;
    }

    if (flags & KGSL_CMD_FLAGS_PMODE) {
        /* re-enable protected mode error checking */
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, 1);
    }

    /* always increment the global timestamp. once. */
    rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
    if (context) {
        if (context_id == KGSL_MEMSTORE_GLOBAL)
            rb->timestamp[context_id] =
                rb->timestamp[KGSL_MEMSTORE_GLOBAL];
        else
            rb->timestamp[context_id]++;
    }
    timestamp = rb->timestamp[context_id];

    /* scratchpad ts for recovery */
    GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
    GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);

    if (adreno_is_a3xx(adreno_dev)) {
        /*
         * FLush HLSQ lazy updates to make sure there are no
         * rsources pending for indirect loads after the timestamp
         */

        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_EVENT_WRITE, 1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); /* HLSQ_FLUSH */
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_WAIT_FOR_IDLE, 1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
    }

    if (context) {
        /* start-of-pipeline timestamp */
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_MEM_WRITE, 2));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
                                          KGSL_MEMSTORE_OFFSET(context->id, soptimestamp)));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);

        /* end-of-pipeline timestamp */
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_EVENT_WRITE, 3));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
        GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
                                          KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp)));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);

        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_MEM_WRITE, 2));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
                                          KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
                                                  eoptimestamp)));
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
    } else {
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_EVENT_WRITE, 3));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
        GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
                                          KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
                                                  eoptimestamp)));
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
    }

    if (!(flags & KGSL_CMD_FLAGS_NO_TS_CMP)) {
        /* Conditional execution based on memory values */
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_COND_EXEC, 4));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
                                          KGSL_MEMSTORE_OFFSET(
                                              context_id, ts_cmp_enable)) >> 2);
        GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
                                          KGSL_MEMSTORE_OFFSET(
                                              context_id, ref_wait_ts)) >> 2);
        GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
        /* # of conditional command DWORDs */
        GSL_RB_WRITE(ringcmds, rcmd_gpu, 2);
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_INTERRUPT, 1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK);
    }
コード例 #7
0
int adreno_ringbuffer_start(struct adreno_ringbuffer *rb, unsigned int init_ram)
{
    int status;
    /*cp_rb_cntl_u cp_rb_cntl; */
    union reg_cp_rb_cntl cp_rb_cntl;
    unsigned int rb_cntl;
    struct kgsl_device *device = rb->device;
    struct adreno_device *adreno_dev = ADRENO_DEVICE(device);

    if (rb->flags & KGSL_FLAGS_STARTED)
        return 0;

    if (init_ram)
        rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;

    kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0,
                       sizeof(struct kgsl_rbmemptrs));

    kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA,
                       (rb->sizedwords << 2));

    if (adreno_is_a2xx(adreno_dev)) {
        adreno_regwrite(device, REG_CP_RB_WPTR_BASE,
                        (rb->memptrs_desc.gpuaddr
                         + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET));

        /* setup WPTR delay */
        adreno_regwrite(device, REG_CP_RB_WPTR_DELAY,
                        0 /*0x70000010 */);
    }

    /*setup REG_CP_RB_CNTL */
    adreno_regread(device, REG_CP_RB_CNTL, &rb_cntl);
    cp_rb_cntl.val = rb_cntl;

    /*
     * The size of the ringbuffer in the hardware is the log2
     * representation of the size in quadwords (sizedwords / 2)
     */
    cp_rb_cntl.f.rb_bufsz = ilog2(rb->sizedwords >> 1);

    /*
     * Specify the quadwords to read before updating mem RPTR.
     * Like above, pass the log2 representation of the blocksize
     * in quadwords.
    */
    cp_rb_cntl.f.rb_blksz = ilog2(KGSL_RB_BLKSIZE >> 3);

    if (adreno_is_a2xx(adreno_dev)) {
        /* WPTR polling */
        cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN;
    }

    /* mem RPTR writebacks */
    cp_rb_cntl.f.rb_no_update =  GSL_RB_CNTL_NO_UPDATE;

    adreno_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val);

    adreno_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr);

    adreno_regwrite(device, REG_CP_RB_RPTR_ADDR,
                    rb->memptrs_desc.gpuaddr +
                    GSL_RB_MEMPTRS_RPTR_OFFSET);

    if (adreno_is_a3xx(adreno_dev)) {
        /* enable access protection to privileged registers */
        adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);

        /* RBBM registers */
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);

        /* CP registers */
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);

        /* RB registers */
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);

        /* VBIF registers */
        adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
    }

    if (adreno_is_a2xx(adreno_dev)) {
        /* explicitly clear all cp interrupts */
        adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
    }

    /* setup scratch/timestamp */
    adreno_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr +
                    KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
                                         soptimestamp));

    adreno_regwrite(device, REG_SCRATCH_UMSK,
                    GSL_RB_MEMPTRS_SCRATCH_MASK);

    /* load the CP ucode */

    status = adreno_ringbuffer_load_pm4_ucode(device);
    if (status != 0)
        return status;

    /* load the prefetch parser ucode */
    status = adreno_ringbuffer_load_pfp_ucode(device);
    if (status != 0)
        return status;

    if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev))
        adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000F0602);

    rb->rptr = 0;
    rb->wptr = 0;

    /* clear ME_HALT to start micro engine */
    adreno_regwrite(device, REG_CP_ME_CNTL, 0);

    /* ME init is GPU specific, so jump into the sub-function */
    adreno_dev->gpudev->rb_init(adreno_dev, rb);

    /* idle device to validate ME INIT */
    status = adreno_idle(device, KGSL_TIMEOUT_DEFAULT);

    if (status == 0)
        rb->flags |= KGSL_FLAGS_STARTED;

    return status;
}
コード例 #8
0
ファイル: adreno_gpu.c プロジェクト: asmalldev/linux
void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
		struct msm_file_private *ctx)
{
	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
	struct msm_drm_private *priv = gpu->dev->dev_private;
	struct msm_ringbuffer *ring = gpu->rb;
	unsigned i;

	for (i = 0; i < submit->nr_cmds; i++) {
		switch (submit->cmd[i].type) {
		case MSM_SUBMIT_CMD_IB_TARGET_BUF:
			/* ignore IB-targets */
			break;
		case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
			/* ignore if there has not been a ctx switch: */
			if (priv->lastctx == ctx)
				break;
		case MSM_SUBMIT_CMD_BUF:
			OUT_PKT3(ring, adreno_is_a430(adreno_gpu) ?
				CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2);
			OUT_RING(ring, submit->cmd[i].iova);
			OUT_RING(ring, submit->cmd[i].size);
			OUT_PKT2(ring);
			break;
		}
	}

	OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);
	OUT_RING(ring, submit->fence->seqno);

	if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) {
		/* Flush HLSQ lazy updates to make sure there is nothing
		 * pending for indirect loads after the timestamp has
		 * passed:
		 */
		OUT_PKT3(ring, CP_EVENT_WRITE, 1);
		OUT_RING(ring, HLSQ_FLUSH);

		OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
		OUT_RING(ring, 0x00000000);
	}

	OUT_PKT3(ring, CP_EVENT_WRITE, 3);
	OUT_RING(ring, CACHE_FLUSH_TS);
	OUT_RING(ring, rbmemptr(adreno_gpu, fence));
	OUT_RING(ring, submit->fence->seqno);

	/* we could maybe be clever and only CP_COND_EXEC the interrupt: */
	OUT_PKT3(ring, CP_INTERRUPT, 1);
	OUT_RING(ring, 0x80000000);

	/* Workaround for missing irq issue on 8x16/a306.  Unsure if the
	 * root cause is a platform issue or some a306 quirk, but this
	 * keeps things humming along:
	 */
	if (adreno_is_a306(adreno_gpu)) {
		OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
		OUT_RING(ring, 0x00000000);
		OUT_PKT3(ring, CP_INTERRUPT, 1);
		OUT_RING(ring, 0x80000000);
	}

#if 0
	if (adreno_is_a3xx(adreno_gpu)) {
		/* Dummy set-constant to trigger context rollover */
		OUT_PKT3(ring, CP_SET_CONSTANT, 2);
		OUT_RING(ring, CP_REG(REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG));
		OUT_RING(ring, 0x00000000);
	}
#endif

	gpu->funcs->flush(gpu);
}
コード例 #9
0
static uint32_t
adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
                          unsigned int flags, unsigned int *cmds,
                          int sizedwords)
{
    struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
    unsigned int *ringcmds;
    unsigned int timestamp;
    unsigned int total_sizedwords = sizedwords + 6;
    unsigned int i;
    unsigned int rcmd_gpu;

    /* reserve space to temporarily turn off protected mode
    *  error checking if needed
    */
    total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
    total_sizedwords += !(flags & KGSL_CMD_FLAGS_NO_TS_CMP) ? 7 : 0;
    total_sizedwords += !(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD) ? 2 : 0;

    if (adreno_is_a3xx(adreno_dev))
        total_sizedwords += 7;

    ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords);
    rcmd_gpu = rb->buffer_desc.gpuaddr
               + sizeof(uint)*(rb->wptr-total_sizedwords);

    if (!(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD)) {
        GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
    }
    if (flags & KGSL_CMD_FLAGS_PMODE) {
        /* disable protected mode error checking */
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
    }

    for (i = 0; i < sizedwords; i++) {
        GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds);
        cmds++;
    }

    if (flags & KGSL_CMD_FLAGS_PMODE) {
        /* re-enable protected mode error checking */
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, 1);
    }

    rb->timestamp++;
    timestamp = rb->timestamp;

    /* start-of-pipeline and end-of-pipeline timestamps */
    GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
    GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp);

    if (adreno_is_a3xx(adreno_dev)) {
        /*
         * FLush HLSQ lazy updates to make sure there are no
         * rsources pending for indirect loads after the timestamp
         */

        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_EVENT_WRITE, 1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); /* HLSQ_FLUSH */
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_WAIT_FOR_IDLE, 1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
    }

    GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3));
    GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
    GSL_RB_WRITE(ringcmds, rcmd_gpu,
                 (rb->device->memstore.gpuaddr +
                  KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp)));
    GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp);

    if (!(flags & KGSL_CMD_FLAGS_NO_TS_CMP)) {
        /* Conditional execution based on memory values */
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_COND_EXEC, 4));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, (rb->device->memstore.gpuaddr +
                                          KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable)) >> 2);
        GSL_RB_WRITE(ringcmds, rcmd_gpu, (rb->device->memstore.gpuaddr +
                                          KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts)) >> 2);
        GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp);
        /* # of conditional command DWORDs */
        GSL_RB_WRITE(ringcmds, rcmd_gpu, 2);
        GSL_RB_WRITE(ringcmds, rcmd_gpu,
                     cp_type3_packet(CP_INTERRUPT, 1));
        GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK);
    }
コード例 #10
0
static uint32_t
adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
				struct adreno_context *context,
				unsigned int flags, unsigned int *cmds,
				int sizedwords)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
	unsigned int *ringcmds;
	unsigned int timestamp;
	unsigned int total_sizedwords = sizedwords;
	unsigned int i;
	unsigned int rcmd_gpu;
	unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
	unsigned int gpuaddr = rb->device->memstore.gpuaddr;

	if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)
		context_id = context->id;

	total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
	total_sizedwords += !(flags & KGSL_CMD_FLAGS_NO_TS_CMP) ? 7 : 0;
	
	total_sizedwords += 2;

	if (adreno_is_a3xx(adreno_dev))
		total_sizedwords += 7;

	total_sizedwords += 2; 
	if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
		total_sizedwords += 3; 
		total_sizedwords += 4; 
		total_sizedwords += 3; 
	} else {
		total_sizedwords += 4; 
	}

	ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords);
	if (context->flags & CTXT_FLAGS_GPU_HANG) {
		KGSL_CTXT_WARN(rb->device,
		"Context %p caused a gpu hang. Will not accept commands for context %d\n",
		context, context->id);
		return rb->timestamp[context_id];
	}

	rcmd_gpu = rb->buffer_desc.gpuaddr
		+ sizeof(uint)*(rb->wptr-total_sizedwords);

	GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
	GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);

	if (flags & KGSL_CMD_FLAGS_PMODE) {
		
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
	}

	for (i = 0; i < sizedwords; i++) {
		GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds);
		cmds++;
	}

	if (flags & KGSL_CMD_FLAGS_PMODE) {
		
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, 1);
	}

	
	rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
	if (context) {
		if (context_id == KGSL_MEMSTORE_GLOBAL)
			rb->timestamp[context_id] =
				rb->timestamp[KGSL_MEMSTORE_GLOBAL];
		else
			rb->timestamp[context_id]++;
	}
	timestamp = rb->timestamp[context_id];

	
	GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
	GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);

	if (adreno_is_a3xx(adreno_dev)) {

		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			cp_type3_packet(CP_EVENT_WRITE, 1));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); 
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			cp_type3_packet(CP_WAIT_FOR_IDLE, 1));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
	}

	if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
		
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			cp_type3_packet(CP_MEM_WRITE, 2));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
			KGSL_MEMSTORE_OFFSET(context->id, soptimestamp)));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);

		
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			cp_type3_packet(CP_EVENT_WRITE, 3));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
			KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp)));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);

		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			cp_type3_packet(CP_MEM_WRITE, 2));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
			      KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
				      eoptimestamp)));
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
	} else {
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			cp_type3_packet(CP_EVENT_WRITE, 3));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
			      KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
				      eoptimestamp)));
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
	}

	if (!(flags & KGSL_CMD_FLAGS_NO_TS_CMP)) {
		
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			cp_type3_packet(CP_COND_EXEC, 4));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
			KGSL_MEMSTORE_OFFSET(
				context_id, ts_cmp_enable)) >> 2);
		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
			KGSL_MEMSTORE_OFFSET(
				context_id, ref_wait_ts)) >> 2);
		GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
		
		GSL_RB_WRITE(ringcmds, rcmd_gpu, 2);
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			cp_type3_packet(CP_INTERRUPT, 1));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK);
	}
コード例 #11
0
int adreno_ringbuffer_start(struct adreno_ringbuffer *rb, unsigned int init_ram)
{
	int status;
	
	union reg_cp_rb_cntl cp_rb_cntl;
	unsigned int rb_cntl;
	struct kgsl_device *device = rb->device;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);

	if (rb->flags & KGSL_FLAGS_STARTED)
		return 0;

	if (init_ram)
		rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;

	kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0,
			   sizeof(struct kgsl_rbmemptrs));

	kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA,
			   (rb->sizedwords << 2));

	if (adreno_is_a2xx(adreno_dev)) {
		adreno_regwrite(device, REG_CP_RB_WPTR_BASE,
			(rb->memptrs_desc.gpuaddr
			+ GSL_RB_MEMPTRS_WPTRPOLL_OFFSET));

		
		adreno_regwrite(device, REG_CP_RB_WPTR_DELAY,
			0 );
	}

	
	adreno_regread(device, REG_CP_RB_CNTL, &rb_cntl);
	cp_rb_cntl.val = rb_cntl;

	cp_rb_cntl.f.rb_bufsz = ilog2(rb->sizedwords >> 1);

	cp_rb_cntl.f.rb_blksz = ilog2(KGSL_RB_BLKSIZE >> 3);

	if (adreno_is_a2xx(adreno_dev)) {
		
		cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN;
	}

	
	cp_rb_cntl.f.rb_no_update =  GSL_RB_CNTL_NO_UPDATE;

	adreno_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val);

	adreno_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr);

	adreno_regwrite(device, REG_CP_RB_RPTR_ADDR,
			     rb->memptrs_desc.gpuaddr +
			     GSL_RB_MEMPTRS_RPTR_OFFSET);

	if (adreno_is_a3xx(adreno_dev)) {
		
		adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);

		
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);

		
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);

		
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);

		
		adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
	}

	if (adreno_is_a2xx(adreno_dev)) {
		
		adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
	}

	
	adreno_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr +
			     KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
				     soptimestamp));

	adreno_regwrite(device, REG_SCRATCH_UMSK,
			     GSL_RB_MEMPTRS_SCRATCH_MASK);

	

	status = adreno_ringbuffer_load_pm4_ucode(device);
	if (status != 0)
		return status;

	
	status = adreno_ringbuffer_load_pfp_ucode(device);
	if (status != 0)
		return status;

	
	if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev))
		adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602);

	rb->rptr = 0;
	rb->wptr = 0;

	
	adreno_regwrite(device, REG_CP_ME_CNTL, 0);

	
	adreno_dev->gpudev->rb_init(adreno_dev, rb);

	
	status = adreno_idle(device, KGSL_TIMEOUT_DEFAULT);

	if (status == 0)
		rb->flags |= KGSL_FLAGS_STARTED;

	return status;
}