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

Commit 028c9be5 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 a power constraints interface"

parents b6cda446 2008f963
Loading
Loading
Loading
Loading
+67 −1
Original line number Diff line number Diff line
@@ -2460,12 +2460,56 @@ static int adreno_getproperty(struct kgsl_device *device,
	return status;
}

static int adreno_setproperty(struct kgsl_device *device,
static int adreno_set_constraint(struct kgsl_device *device,
				struct kgsl_context *context,
				struct kgsl_device_constraint *constraint)
{
	int status = 0;

	switch (constraint->type) {
	case KGSL_CONSTRAINT_PWRLEVEL: {
		struct kgsl_device_constraint_pwrlevel pwr;

		if (constraint->size != sizeof(pwr)) {
			status = -EINVAL;
			break;
		}

		if (copy_from_user(&pwr,
				(void __user *)constraint->data,
				sizeof(pwr))) {
			status = -EFAULT;
			break;
		}
		if (pwr.level >= KGSL_CONSTRAINT_PWR_MAXLEVELS) {
			status = -EINVAL;
			break;
		}

		context->pwr_constraint.type =
				KGSL_CONSTRAINT_PWRLEVEL;
		context->pwr_constraint.sub_type = pwr.level;
		}
		break;
	case KGSL_CONSTRAINT_NONE:
		context->pwr_constraint.type = KGSL_CONSTRAINT_NONE;
		break;

	default:
		status = -EINVAL;
		break;
	}

	return status;
}

static int adreno_setproperty(struct kgsl_device_private *dev_priv,
				enum kgsl_property_type type,
				void __user *value,
				unsigned int sizebytes)
{
	int status = -EINVAL;
	struct kgsl_device *device = dev_priv->device;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);

	switch (type) {
@@ -2502,6 +2546,28 @@ static int adreno_setproperty(struct kgsl_device *device,
			status = 0;
		}
		break;
	case KGSL_PROP_PWR_CONSTRAINT: {
			struct kgsl_device_constraint constraint;
			struct kgsl_context *context;

			if (sizebytes != sizeof(constraint))
				break;

			if (copy_from_user(&constraint, value,
				sizeof(constraint))) {
				status = -EFAULT;
				break;
			}

			context = kgsl_context_get_owner(dev_priv,
							constraint.context_id);
			if (context == NULL)
				break;
			status = adreno_set_constraint(device, context,
								&constraint);
			kgsl_context_put(context);
		}
		break;
	default:
		break;
	}
+3 −2
Original line number Diff line number Diff line
/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2002,2007-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -334,7 +334,8 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
		KGSL_CONTEXT_NO_FAULT_TOLERANCE |
		KGSL_CONTEXT_CTX_SWITCH |
		KGSL_CONTEXT_PRIORITY_MASK |
		KGSL_CONTEXT_TYPE_MASK);
		KGSL_CONTEXT_TYPE_MASK |
		KGSL_CONTEXT_PWR_CONSTRAINT);

	/* Always enable per-context timestamps */
	drawctxt->base.flags |= KGSL_CONTEXT_PER_CONTEXT_TS;
+63 −1
Original line number Diff line number Diff line
/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2002,2007-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -1102,6 +1102,65 @@ adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv,
	return ret;
}

unsigned int adreno_ringbuffer_get_constraint(struct kgsl_device *device,
				struct kgsl_context *context)
{
	unsigned int pwrlevel = device->pwrctrl.active_pwrlevel;

	switch (context->pwr_constraint.type) {
	case KGSL_CONSTRAINT_PWRLEVEL: {
		switch (context->pwr_constraint.sub_type) {
		case KGSL_CONSTRAINT_PWR_MAX:
			pwrlevel = device->pwrctrl.max_pwrlevel;
			break;
		case KGSL_CONSTRAINT_PWR_MIN:
			pwrlevel = device->pwrctrl.min_pwrlevel;
			break;
		default:
			break;
		}
	}
	break;

	}

	return pwrlevel;
}

void adreno_ringbuffer_set_constraint(struct kgsl_device *device,
			struct kgsl_cmdbatch *cmdbatch)
{
	unsigned int constraint;
	struct kgsl_context *context = cmdbatch->context;
	/*
	 * Check if the context has a constraint and constraint flags are
	 * set.
	 */
	if (context->pwr_constraint.type &&
		((context->flags & KGSL_CONTEXT_PWR_CONSTRAINT) ||
			(cmdbatch->flags & KGSL_CONTEXT_PWR_CONSTRAINT))) {

		constraint = adreno_ringbuffer_get_constraint(device, context);

		/*
		 * If a constraint is already set, set a new
		 * constraint only if it is faster
		 */
		if ((device->pwrctrl.constraint.type ==
			KGSL_CONSTRAINT_NONE) || (constraint <
			device->pwrctrl.constraint.hint.pwrlevel.level)) {

			kgsl_pwrctrl_pwrlevel_change(device, constraint);
			device->pwrctrl.constraint.type =
					context->pwr_constraint.type;
			device->pwrctrl.constraint.hint.
					pwrlevel.level = constraint;
		}

	}

}

/* adreno_rindbuffer_submitcmd - submit userspace IBs to the GPU */
int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
		struct kgsl_cmdbatch *cmdbatch)
@@ -1212,6 +1271,9 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
		test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv))
		flags |= KGSL_CMD_FLAGS_PWRON_FIXUP;

	/* Set the constraints before adding to ringbuffer */
	adreno_ringbuffer_set_constraint(device, cmdbatch);

	ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
					drawctxt,
					flags,
+2 −2
Original line number Diff line number Diff line
@@ -1335,8 +1335,8 @@ long kgsl_ioctl_device_setproperty(struct kgsl_device_private *dev_priv,

	if (dev_priv->device->ftbl->setproperty)
		result = dev_priv->device->ftbl->setproperty(
			dev_priv->device, param->type,
			param->value, param->sizebytes);
			dev_priv, param->type, param->value,
			param->sizebytes);

	return result;
}
+4 −2
Original line number Diff line number Diff line
/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2002,2007-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -136,7 +136,7 @@ struct kgsl_functable {
	void (*drawctxt_destroy) (struct kgsl_context *context);
	long (*ioctl) (struct kgsl_device_private *dev_priv,
		unsigned int cmd, void *data);
	int (*setproperty) (struct kgsl_device *device,
	int (*setproperty) (struct kgsl_device_private *dev_priv,
		enum kgsl_property_type type, void __user *value,
		unsigned int sizebytes);
	void (*drawctxt_sched)(struct kgsl_device *device,
@@ -362,6 +362,7 @@ struct kgsl_process_private;
 * @pagefault_ts: global timestamp of the pagefault, if KGSL_CONTEXT_PAGEFAULT
 * is set.
 * @flags: flags from userspace controlling the behavior of this context
 * @pwr_constraint: power constraint from userspace for this context
 */
struct kgsl_context {
	struct kref refcount;
@@ -380,6 +381,7 @@ struct kgsl_context {
	struct list_head events_list;
	unsigned int pagefault_ts;
	unsigned int flags;
	struct kgsl_pwr_constraint pwr_constraint;
};

/**
Loading