Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c6bdd57 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: consolidate preamble based context switch code"

parents 73fa3ec8 ad6790ba
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -362,10 +362,6 @@ struct adreno_gpudev {

	/* GPU specific function hooks */
	int (*ctxt_create)(struct adreno_device *, struct adreno_context *);
	int (*ctxt_save)(struct adreno_device *, struct adreno_context *);
	int (*ctxt_restore)(struct adreno_device *, struct adreno_context *);
	int (*ctxt_draw_workaround)(struct adreno_device *,
					struct adreno_context *);
	irqreturn_t (*irq_handler)(struct adreno_device *);
	void (*irq_control)(struct adreno_device *, int);
	unsigned int (*irq_pending)(struct adreno_device *);
+50 −39
Original line number Diff line number Diff line
@@ -1398,11 +1398,56 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev,
	return 0;
}

static void a2xx_drawctxt_detach(struct adreno_context *drawctxt)
{
	kgsl_sharedmem_free(&drawctxt->gpustate);
	kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
}

static int a2xx_drawctxt_save(struct adreno_device *adreno_dev,
			struct adreno_context *context);

static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
			struct adreno_context *context);

static int a2xx_drawctxt_draw_workaround(struct adreno_device *adreno_dev,
					struct adreno_context *context);

static const struct adreno_context_ops a225_preamble_ctx_ops = {
	.restore = adreno_context_restore,
	.draw_workaround = a2xx_drawctxt_draw_workaround,
};

static const struct adreno_context_ops a225_legacy_ctx_ops = {
	.save = a2xx_drawctxt_save,
	.restore = a2xx_drawctxt_restore,
	.draw_workaround = a2xx_drawctxt_draw_workaround,
	.detach = a2xx_drawctxt_detach,
};

static const struct adreno_context_ops a2xx_legacy_ctx_ops = {
	.save = a2xx_drawctxt_save,
	.restore = a2xx_drawctxt_restore,
	.detach = a2xx_drawctxt_detach,
};


static int a2xx_drawctxt_create(struct adreno_device *adreno_dev,
	struct adreno_context *drawctxt)
{
	int ret;

	if (drawctxt->flags & CTXT_FLAGS_PREAMBLE
	   && drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC) {
		drawctxt->ops = (adreno_is_a225(adreno_dev))
			?  &a225_preamble_ctx_ops : &adreno_preamble_ctx_ops;

		return 0;
	}

	drawctxt->ops = (adreno_is_a225(adreno_dev))
			?  &a225_legacy_ctx_ops : &a2xx_legacy_ctx_ops;

	/*
	 * Allocate memory for the GPU state and the context commands.
	 * Despite the name, this is much more then just storage for
@@ -1510,12 +1555,6 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev,
	struct kgsl_device *device = &adreno_dev->dev;
	int ret;

	if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTROYED))
		return 0;

	if (context->state == ADRENO_CONTEXT_STATE_INVALID)
		return 0;

	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
			context->reg_save[1],
@@ -1600,40 +1639,14 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
			struct adreno_context *context)
{
	struct kgsl_device *device = &adreno_dev->dev;
	unsigned int cmds[5];
	int ret = 0;

	if (context == NULL) {
		/* No context - set the default pagetable and thats it */
		unsigned int id;
		/*
		 * If there isn't a current context, the kgsl_mmu_setstate
		 * will use the CPU path so we don't need to give
		 * it a valid context id.
		 */
		id = (adreno_dev->drawctxt_active != NULL)
			? adreno_dev->drawctxt_active->base.id
			: KGSL_CONTEXT_INVALID;
		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
				  id);
		return 0;
	}
	int ret;

	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;
	ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
					cmds, 5);
	ret = adreno_context_restore(adreno_dev, context);
	if (ret)
		return ret;

	kgsl_mmu_setstate(&device->mmu, context->base.proc_priv->pagetable,
			context->base.id);

	/* restore gmem.
	/*
	 *  restore gmem.
	 *  (note: changes shader. shader must not already be restored.)
	 */
	if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
@@ -1692,6 +1705,7 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
	}

	if (adreno_is_a20x(adreno_dev)) {
		unsigned int cmds[2];
		cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
		cmds[1] = context->bin_base_offset;
		ret = adreno_ringbuffer_issuecmds(device, context,
@@ -2296,9 +2310,6 @@ struct adreno_gpudev adreno_a2xx_gpudev = {
	.reg_offsets = &a2xx_reg_offsets,

	.ctxt_create = a2xx_drawctxt_create,
	.ctxt_save = a2xx_drawctxt_save,
	.ctxt_restore = a2xx_drawctxt_restore,
	.ctxt_draw_workaround = a2xx_drawctxt_draw_workaround,
	.irq_handler = a2xx_irq_handler,
	.irq_control = a2xx_irq_control,
	.irq_pending = a2xx_irq_pending,
+30 −39
Original line number Diff line number Diff line
@@ -2345,17 +2345,40 @@ static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev,
	return 0;
}

static void a3xx_drawctxt_detach(struct adreno_context *drawctxt)
{
	kgsl_sharedmem_free(&drawctxt->gpustate);
	kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
}

static int a3xx_drawctxt_save(struct adreno_device *adreno_dev,
			   struct adreno_context *context);

static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev,
			      struct adreno_context *context);

static const struct adreno_context_ops a3xx_legacy_ctx_ops = {
	.save = a3xx_drawctxt_save,
	.restore = a3xx_drawctxt_restore,
	.detach = a3xx_drawctxt_detach,
};


static int a3xx_drawctxt_create(struct adreno_device *adreno_dev,
	struct adreno_context *drawctxt)
{
	int ret;

	/*
	 * Allocate memory for the GPU state and the context commands.
	 * Despite the name, this is much more then just storage for
	 * the gpustate.  This contains command space for gmem save
	 * and texture and vertex buffer storage too
	 * Nothing to do here if the context is using preambles and doesn't need
	 * GMEM save/restore
	 */
	if ((drawctxt->flags & CTXT_FLAGS_PREAMBLE) &&
		(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) {
		drawctxt->ops = &adreno_preamble_ctx_ops;
		return 0;
	}
	drawctxt->ops = &a3xx_legacy_ctx_ops;

	ret = kgsl_allocate(&drawctxt->gpustate,
		drawctxt->base.proc_priv->pagetable, CONTEXT_SIZE);
@@ -2391,9 +2414,6 @@ static int a3xx_drawctxt_save(struct adreno_device *adreno_dev,
	struct kgsl_device *device = &adreno_dev->dev;
	int ret;

	if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTROYED))
		return 0;

	if (context->state == ADRENO_CONTEXT_STATE_INVALID)
		return 0;

@@ -2451,39 +2471,13 @@ static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev,
			      struct adreno_context *context)
{
	struct kgsl_device *device = &adreno_dev->dev;
	unsigned int cmds[5];
	int ret = 0;

	if (context == NULL) {
		/* No context - set the default pagetable and thats it */
		unsigned int id;
		/*
		 * If there isn't a current context, the kgsl_mmu_setstate
		 * will use the CPU path so we don't need to give
		 * it a valid context id.
		 */
		id = (adreno_dev->drawctxt_active != NULL)
			? adreno_dev->drawctxt_active->base.id
			: KGSL_CONTEXT_INVALID;
		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
				  id);
		return 0;
	}
	int ret;

	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;
	ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
					cmds, 5);
	/* do the common part */
	ret = adreno_context_restore(adreno_dev, context);
	if (ret)
		return ret;

	kgsl_mmu_setstate(&device->mmu, context->base.proc_priv->pagetable,
			context->base.id);

	/*
	 * Restore GMEM.  (note: changes shader.
	 * Shader must not already be restored.)
@@ -4401,9 +4395,6 @@ struct adreno_gpudev adreno_a3xx_gpudev = {
	.perfcounters = &a3xx_perfcounters,

	.ctxt_create = a3xx_drawctxt_create,
	.ctxt_save = a3xx_drawctxt_save,
	.ctxt_restore = a3xx_drawctxt_restore,
	.ctxt_draw_workaround = NULL,
	.rb_init = a3xx_rb_init,
	.perfcounter_init = a3xx_perfcounter_init,
	.perfcounter_close = a3xx_perfcounter_close,
+0 −66
Original line number Diff line number Diff line
@@ -106,70 +106,6 @@ const unsigned int a4xx_registers[] = {

const unsigned int a4xx_registers_count = ARRAY_SIZE(a4xx_registers) / 2;

static int a4xx_drawctxt_create(struct adreno_device *adreno_dev,
	struct adreno_context *drawctxt)
{
	int ret = 0;
	struct kgsl_device *device = &adreno_dev->dev;

	if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
		/* This option is not supported on a4xx */
		KGSL_DRV_ERR(device,
			"Preambles required for A4XX draw contexts\n");
		ret = -EPERM;
		goto done;
	}

	if (!(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) {
		/* This option is not supported on a4xx */
		KGSL_DRV_ERR(device,
			"Cannot create context with gmemalloc\n");
		ret = -EPERM;
	}

done:
	return ret;
}

static int a4xx_drawctxt_restore(struct adreno_device *adreno_dev,
			      struct adreno_context *context)
{
	struct kgsl_device *device = &adreno_dev->dev;
	unsigned int cmds[5];
	int ret;

	if (context == NULL) {
		/* No context - set the default pagetable and thats it */
		unsigned int id;
		/*
		 * If there isn't a current context, the kgsl_mmu_setstate
		 * will use the CPU path so we don't need to give
		 * it a valid context id.
		 */
		id = (adreno_dev->drawctxt_active != NULL)
			? adreno_dev->drawctxt_active->base.id
			: KGSL_CONTEXT_INVALID;
		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
				  id);
		return 0;
	}

	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;
	ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
					cmds, 5);
	if (ret)
		return ret;
	ret = kgsl_mmu_setstate(&device->mmu,
			context->base.proc_priv->pagetable,
			context->base.id);
	return ret;
}

static const struct adreno_vbif_data a420_vbif[] = {
	{ A4XX_VBIF_ABIT_SORT, 0x0001001F },
	{ A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4 },
@@ -294,8 +230,6 @@ const struct adreno_reg_offsets a4xx_reg_offsets = {
struct adreno_gpudev adreno_a4xx_gpudev = {
	.reg_offsets = &a4xx_reg_offsets,

	.ctxt_create = a4xx_drawctxt_create,
	.ctxt_restore = a4xx_drawctxt_restore,
	.rb_init = a3xx_rb_init,
	.irq_control = a3xx_irq_control,
	.irq_handler = a3xx_irq_handler,
+109 −36
Original line number Diff line number Diff line
@@ -458,9 +458,20 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
	drawctxt->type =
		(*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT;

	if (adreno_dev->gpudev->ctxt_create) {
		ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
		if (ret)
			goto err;
	} else if ((*flags & KGSL_CONTEXT_PREAMBLE) == 0 ||
		  (*flags & KGSL_CONTEXT_NO_GMEM_ALLOC) == 0) {
		KGSL_DEV_ERR_ONCE(device,
				"legacy context switch not supported\n");
		ret = -EINVAL;
		goto err;

	} else {
		drawctxt->ops = &adreno_preamble_ctx_ops;
	}

	kgsl_sharedmem_writel(device, &device->memstore,
			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp),
@@ -510,19 +521,8 @@ int adreno_drawctxt_detach(struct kgsl_context *context)
	drawctxt = ADRENO_CONTEXT(context);

	/* deactivate context */
	if (adreno_dev->drawctxt_active == drawctxt) {
		/* no need to save GMEM or shader, the context is
		 * being destroyed.
		 */
		drawctxt->flags &= ~(CTXT_FLAGS_GMEM_SAVE |
				     CTXT_FLAGS_SHADER_SAVE |
				     CTXT_FLAGS_GMEM_SHADOW |
				     CTXT_FLAGS_STATE_SHADOW);

		drawctxt->flags |= CTXT_FLAGS_BEING_DESTROYED;

	if (adreno_dev->drawctxt_active == drawctxt)
		adreno_drawctxt_switch(adreno_dev, NULL, 0);
	}

	mutex_lock(&drawctxt->mutex);

@@ -568,8 +568,8 @@ int adreno_drawctxt_detach(struct kgsl_context *context)

	adreno_profile_process_results(device);

	kgsl_sharedmem_free(&drawctxt->gpustate);
	kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
	if (drawctxt->ops->detach)
		drawctxt->ops->detach(drawctxt);

	/* wake threads waiting to submit commands from this context */
	wake_up_interruptible_all(&drawctxt->waiting);
@@ -589,6 +589,69 @@ void adreno_drawctxt_destroy(struct kgsl_context *context)
	kfree(drawctxt);
}


/**
 * 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.
 * May be called directly from the adreno_context_ops.restore function
 * pointer or as the first action in a hardware specific restore
 * function.
 */
int adreno_context_restore(struct adreno_device *adreno_dev,
				  struct adreno_context *context)
{
	int ret;
	struct kgsl_device *device;
	unsigned int cmds[5];

	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;
	ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
					cmds, 5);
	if (ret)
		return ret;

	return kgsl_mmu_setstate(&device->mmu,
			context->base.proc_priv->pagetable,
			context->base.id);
}


const struct adreno_context_ops adreno_preamble_ctx_ops = {
	.restore = adreno_context_restore,
};

/**
 * context_save() - save old context when necessary
 * @drawctxt - the old context
 *
 * For legacy context switching, we need to issue save
 * commands unless the context is being destroyed.
 */
static inline int context_save(struct adreno_device *adreno_dev,
				struct adreno_context *context)
{
	if (context->ops->save == NULL
		|| kgsl_context_detached(&context->base)
		|| context->state == ADRENO_CONTEXT_STATE_INVALID)
		return 0;

	return context->ops->save(adreno_dev, context);
}

/**
 * adreno_drawctxt_set_bin_base_offset - set bin base offset for the context
 * @device - KGSL device that owns the context
@@ -627,6 +690,12 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,
	int ret = 0;

	if (drawctxt) {
		/*
		* Handle legacy gmem / save restore flag on each IB.
		* Userspace sets to guard IB sequences that require
		* gmem to be saved and clears it at the end of the
		* sequence.
		*/
		if (flags & KGSL_CONTEXT_SAVE_GMEM)
			/* Set the flag in context so that the save is done
			* when this context is switched out. */
@@ -638,31 +707,25 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,

	/* already current? */
	if (adreno_dev->drawctxt_active == drawctxt) {
		if (adreno_dev->gpudev->ctxt_draw_workaround &&
			adreno_is_a225(adreno_dev))
				ret = adreno_dev->gpudev->ctxt_draw_workaround(
					adreno_dev, drawctxt);
		if (drawctxt && drawctxt->ops->draw_workaround)
			ret = drawctxt->ops->draw_workaround(adreno_dev,
							 drawctxt);
		return ret;
	}

	trace_adreno_drawctxt_switch(adreno_dev->drawctxt_active,
		drawctxt, flags);

	/* Save the old context */
	if (adreno_dev->gpudev->ctxt_save) {
		ret = adreno_dev->gpudev->ctxt_save(adreno_dev,
			adreno_dev->drawctxt_active);

	if (adreno_dev->drawctxt_active) {
		ret = context_save(adreno_dev, adreno_dev->drawctxt_active);
		if (ret) {
			KGSL_DRV_ERR(device,
				"Error in GPU context %d save: %d\n",
				adreno_dev->drawctxt_active->base.id, ret);
			return ret;
		}
	}

		/* Put the old instance of the active drawctxt */
	if (adreno_dev->drawctxt_active) {
		kgsl_context_put(&adreno_dev->drawctxt_active->base);
		adreno_dev->drawctxt_active = NULL;
	}
@@ -671,16 +734,26 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,
	if (drawctxt) {
		if (!_kgsl_context_get(&drawctxt->base))
			return -EINVAL;
	}

		/* Set the new context */
	ret = adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
		ret = drawctxt->ops->restore(adreno_dev, drawctxt);
		if (ret) {
			KGSL_DRV_ERR(device,
					"Error in GPU context %d restore: %d\n",
			drawctxt ? drawctxt->base.id : 0, ret);
					drawctxt->base.id, ret);
			return ret;
		}
	} else {
		/*
		 * No context - set the default pagetable and thats it.
		 * If there isn't a current context, the kgsl_mmu_setstate
		 * will use the CPU path so we don't need to give
		 * it a valid context id.
		 */
		ret = kgsl_mmu_setstate(&device->mmu,
					 device->mmu.defaultpagetable,
					 KGSL_CONTEXT_INVALID);
	}

	adreno_dev->drawctxt_active = drawctxt;
	return 0;
Loading