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

Commit f02365f5 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: Add ringbuffer priority levels"

parents 31b6b840 6fef3054
Loading
Loading
Loading
Loading
+78 −25
Original line number Diff line number Diff line
@@ -1339,7 +1339,7 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
	if (result)
		kgsl_mmu_disable_clk(&device->mmu, KGSL_IOMMU_MAX_UNITS);
	else
		kgsl_mmu_disable_clk_on_ts(&device->mmu, rb->global_ts,
		adreno_ringbuffer_mmu_disable_clk_on_ts(device, rb,
						KGSL_IOMMU_MAX_UNITS);

done:
@@ -1811,7 +1811,7 @@ static int adreno_remove(struct platform_device *pdev)
static int adreno_init(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_gpudev *gpudev;
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	int i;
	int ret;

@@ -1823,8 +1823,6 @@ static int adreno_init(struct kgsl_device *device)
	if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv))
		return 0;

	gpudev = ADRENO_GPU_DEVICE(adreno_dev);

	/* Power up the device */
	ret = kgsl_pwrctrl_enable(device);
	if (ret)
@@ -2083,6 +2081,8 @@ static int adreno_stop(struct kgsl_device *device)

	adreno_dispatcher_stop(adreno_dev);

	adreno_ringbuffer_stop(adreno_dev);

	kgsl_mmu_stop(&device->mmu);

	adreno_irqctrl(adreno_dev, 0);
@@ -3203,6 +3203,74 @@ static int adreno_waittimestamp(struct kgsl_device *device,
	return ret;
}

/**
 * __adreno_readtimestamp() - Reads the timestamp from memstore memory
 * @device: Pointer to device whose memstore is read
 * @index: Index into the memstore memory
 * @type: Type of timestamp to read
 * @timestamp: The out parameter where the timestamp is read
 */
int __adreno_readtimestamp(struct kgsl_device *device, int index, int type,
		unsigned int *timestamp)
{
	int status = 0;

	switch (type) {
	case KGSL_TIMESTAMP_CONSUMED:
		kgsl_sharedmem_readl(&device->memstore, timestamp,
			KGSL_MEMSTORE_OFFSET(index, soptimestamp));
		break;
	case KGSL_TIMESTAMP_RETIRED:
		kgsl_sharedmem_readl(&device->memstore, timestamp,
			KGSL_MEMSTORE_OFFSET(index, eoptimestamp));
		break;
	default:
		status = -EINVAL;
		*timestamp = 0;
		break;
	}
	return status;
}

/**
 * adreno_rb_readtimestamp(): Return the value of given type of timestamp
 * for a RB
 * @device: GPU device whose timestamp values are being queried
 * @priv: The object being queried for a timestamp (expected to be a rb pointer)
 * @type: The type of timestamp (one of 3) to be read
 * @timestamp: Pointer to where the read timestamp is to be written to
 *
 * CONSUMED and RETIRED type timestamps are sorted by id and are constantly
 * updated by the GPU through shared memstore memory. QUEUED type timestamps
 * are read directly from context struct.

 * The function returns 0 on success and timestamp value at the *timestamp
 * address and returns -EINVAL on any read error/invalid type and timestamp = 0.
 */
int adreno_rb_readtimestamp(struct kgsl_device *device,
		void *priv, enum kgsl_timestamp_type type,
		unsigned int *timestamp)
{
	int status = 0;
	struct adreno_ringbuffer *rb = priv;

	/*
	 * If user passed in a NULL pointer for timestamp, return without
	 * doing anything.
	 */
	if (!timestamp)
		return status;

	if (KGSL_TIMESTAMP_QUEUED == type)
		*timestamp = rb->timestamp;
	else
		status = __adreno_readtimestamp(device,
				rb->id + KGSL_MEMSTORE_MAX,
				type, timestamp);

	return status;
}

/**
 * adreno_readtimestamp(): Return the value of given type of timestamp
 * @device: GPU device whose timestamp values are being queried
@@ -3225,6 +3293,7 @@ static int adreno_readtimestamp(struct kgsl_device *device,
	struct kgsl_context *context = priv;
	unsigned int id = KGSL_CONTEXT_ID(context);

	BUG_ON(NULL == context || id >= KGSL_MEMSTORE_MAX);
	/*
	 * If user passed in a NULL pointer for timestamp, return without
	 * doing anything.
@@ -3232,27 +3301,11 @@ static int adreno_readtimestamp(struct kgsl_device *device,
	if (!timestamp)
		return status;

	switch (type) {
	case KGSL_TIMESTAMP_QUEUED: {
		struct adreno_device *adreno_dev = ADRENO_DEVICE(device);

		*timestamp = adreno_context_timestamp(context,
				ADRENO_CURRENT_RINGBUFFER(adreno_dev));
		break;
	}
	case KGSL_TIMESTAMP_CONSUMED:
		kgsl_sharedmem_readl(&device->memstore, timestamp,
			KGSL_MEMSTORE_OFFSET(id, soptimestamp));
		break;
	case KGSL_TIMESTAMP_RETIRED:
		kgsl_sharedmem_readl(&device->memstore, timestamp,
			KGSL_MEMSTORE_OFFSET(id, eoptimestamp));
		break;
	default:
		status = -EINVAL;
		*timestamp = 0;
		break;
	}
	if (KGSL_TIMESTAMP_QUEUED == type)
		*timestamp = adreno_context_timestamp(context);
	else
		status = __adreno_readtimestamp(device,
				context->id, type, timestamp);

	return status;
}
+37 −8
Original line number Diff line number Diff line
@@ -605,6 +605,7 @@ struct adreno_gpudev {
	struct adreno_coresight *coresight;

	struct adreno_irq *irq;
	int num_prio_levels;
	/* GPU specific function hooks */
	irqreturn_t (*irq_handler)(struct adreno_device *);
	void (*irq_control)(struct adreno_device *, int);
@@ -778,6 +779,10 @@ void adreno_coresight_remove(struct kgsl_device *device);

bool adreno_hw_isidle(struct kgsl_device *device);

int adreno_rb_readtimestamp(struct kgsl_device *device,
	void *priv, enum kgsl_timestamp_type type,
	unsigned int *timestamp);

static inline int adreno_is_a3xx(struct adreno_device *adreno_dev)
{
	return ((ADRENO_GPUREV(adreno_dev) >= 300) &&
@@ -860,19 +865,14 @@ static inline int adreno_rb_ctxtswitch(unsigned int *cmd)
/**
 * adreno_context_timestamp() - Return the last queued timestamp for the context
 * @k_ctxt: Pointer to the KGSL context to query
 * @rb: Pointer to the ringbuffer structure for the GPU
 *
 * Return the last queued context for the given context. This is used to verify
 * that incoming requests are not using an invalid (unsubmitted) timestamp
 */
static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt,
		struct adreno_ringbuffer *rb)
static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt)
{
	if (k_ctxt) {
		struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
		return a_ctxt->timestamp;
	}
	return rb->global_ts;
	struct adreno_context *drawctxt = ADRENO_CONTEXT(k_ctxt);
	return drawctxt->timestamp;
}

static inline int __adreno_add_idle_indirect_cmds(unsigned int *cmds,
@@ -1292,4 +1292,33 @@ adreno_get_rptr(struct adreno_ringbuffer *rb)
	return rb->rptr;
}

/**
 * adreno_ctx_get_rb() - Return the ringbuffer that a context should
 * use based on priority
 * @adreno_dev: The adreno device that context is using
 * @drawctxt: The context pointer
 */
static inline struct adreno_ringbuffer *adreno_ctx_get_rb(
				struct adreno_device *adreno_dev,
				struct adreno_context *drawctxt)
{
	struct kgsl_context *context;
	int level;
	if (!drawctxt)
		return NULL;

	context = &(drawctxt->base);

	/*
	 * Math to convert the priority field in context structure to an RB ID.
	 * Divide up the context priority based on number of ringbuffer levels.
	 */
	level = context->priority / adreno_dev->num_ringbuffers;
	if (level < adreno_dev->num_ringbuffers)
		return &(adreno_dev->ringbuffers[level]);
	else
		return &(adreno_dev->ringbuffers[
				adreno_dev->num_ringbuffers - 1]);
}

#endif /*__ADRENO_H */
+1 −0
Original line number Diff line number Diff line
@@ -2482,6 +2482,7 @@ struct adreno_gpudev adreno_a3xx_gpudev = {
	.perfcounters = &a3xx_perfcounters,
	.irq = &a3xx_irq,
	.snapshot_data = &a3xx_snapshot_data,
	.num_prio_levels = 1,

	.rb_init = a3xx_rb_init,
	.perfcounter_init = a3xx_perfcounter_init,
+1 −0
Original line number Diff line number Diff line
@@ -1394,6 +1394,7 @@ struct adreno_gpudev adreno_a4xx_gpudev = {
	.perfcounters = &a4xx_perfcounters,
	.irq = &a4xx_irq,
	.snapshot_data = &a4xx_snapshot_data,
	.num_prio_levels = 1,

	.perfcounter_init = a3xx_perfcounter_init,
	.perfcounter_close = a3xx_perfcounter_close,
+28 −17
Original line number Diff line number Diff line
@@ -57,23 +57,25 @@ static unsigned int _fault_timer_interval = 200;
/* Local array for the current set of fault detect registers */
static unsigned int fault_detect_regs[FT_DETECT_REGS_COUNT];

/* The last retired global timestamp read during fault detect */
static unsigned int fault_detect_ts;

/**
 * fault_detect_read() - Read the set of fault detect registers
 * @device: Pointer to the KGSL device struct
 *
 * Read the set of fault detect registers and store them in the local array.
 * This is for the initial values that are compared later with
 * fault_detect_read_compare
 * fault_detect_read_compare. Also store the initial timestamp of each rb
 * to compare the timestamps with.
 */
static void fault_detect_read(struct kgsl_device *device)
{
	int i;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);

	kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED,
		&fault_detect_ts);
	for (i = 0; i < adreno_dev->num_ringbuffers; i++) {
		struct adreno_ringbuffer *rb = &(adreno_dev->ringbuffers[i]);
		adreno_rb_readtimestamp(device, rb,
			KGSL_TIMESTAMP_RETIRED, &(rb->fault_detect_ts));
	}

	for (i = 0; i < FT_DETECT_REGS_COUNT; i++) {
		if (ft_detect_regs[i] == 0)
@@ -99,12 +101,16 @@ static inline bool _isidle(struct kgsl_device *device)
	if (!adreno_hw_isidle(device))
		return false;

	for (i = 0; i < adreno_dev->num_ringbuffers; i++) {
		kgsl_readtimestamp(device, NULL,
				KGSL_TIMESTAMP_RETIRED, &ts);
		if (ts != adreno_dev->ringbuffers[i].global_ts)
	/*
	 * only compare the current RB timestamp because the device has gone
	 * idle and therefore only the current RB ts can be equal, the other
	 * RB's may not be scheduled by dispatcher yet
	 */
	if (adreno_rb_readtimestamp(device,
		adreno_dev->cur_rb, KGSL_TIMESTAMP_RETIRED, &ts))
		return false;
	if (ts != adreno_dev->cur_rb->timestamp)
		return false;
	}
ret:
	for (i = 0; i < FT_DETECT_REGS_COUNT; i++)
		fault_detect_regs[i] = 0;
@@ -117,10 +123,13 @@ ret:
 * @device: Pointer to the KGSL device struct
 *
 * Read the set of fault detect registers and compare them to the current set
 * of registers.  Return 1 if any of the register values changed
 * of registers.  Return 1 if any of the register values changed. Also, compare
 * if the current RB's timstamp has changed or not.
 */
static int fault_detect_read_compare(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_ringbuffer *rb = ADRENO_CURRENT_RINGBUFFER(adreno_dev);
	int i, ret = 0;
	unsigned int ts;

@@ -139,11 +148,13 @@ static int fault_detect_read_compare(struct kgsl_device *device)
		fault_detect_regs[i] = val;
	}

	kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED, &ts);
	if (ts != fault_detect_ts)
	if (!adreno_rb_readtimestamp(device, adreno_dev->cur_rb,
				KGSL_TIMESTAMP_RETIRED, &ts)) {
		if (ts != rb->fault_detect_ts)
			ret = 1;

	fault_detect_ts = ts;
		rb->fault_detect_ts = ts;
	}

	return ret;
}
Loading