示例#1
0
/**
 * kgsl_cmdbatch_create_compat() - Compat helper to _kgsl_cmdbatch_create()
 * @device: Pointer to the KGSL device struct for the GPU
 * @flags: Flags passed in from the user command
 * @cmdlist: Pointer to the list of commands from the user. Should point to a
 * kgsl_ibdesc_compat struct
 * @numcmds: Number of commands in the list
 * @synclist: Pointer to the list of syncpoints from the user. Should point to
 * a kgsl_cmd_syncpoint_compat struct
 * @numsyncs: Number of syncpoints in the list
 *
 * This function is called from _kgsl_cmdbatch_create(), if the user process
 * submitting cmds is 32 bit, instead of executing rest of the function.
 * It is needed since we do multiple copy_from_user() calls which would
 * otherwise be copying user data into the wrongly sized/structured struct.
 */
int kgsl_cmdbatch_create_compat(struct kgsl_device *device, unsigned int flags,
			struct kgsl_cmdbatch *cmdbatch, void __user *cmdlist,
			unsigned int numcmds, void __user *synclist,
			unsigned int numsyncs)
{
	int ret = 0, i;

	if (!(flags & (KGSL_CMDBATCH_SYNC | KGSL_CMDBATCH_MARKER))) {
		struct kgsl_ibdesc_compat ibdesc32;
		struct kgsl_ibdesc ibdesc;
		void __user *uptr = cmdlist;

		for (i = 0; i < numcmds; i++) {
			memset(&ibdesc32, 0, sizeof(ibdesc32));

			if (copy_from_user(&ibdesc32, uptr, sizeof(ibdesc32))) {
				ret = -EFAULT;
				goto done;
			}

			ibdesc.gpuaddr = (unsigned long)ibdesc32.gpuaddr;
			ibdesc.sizedwords = (size_t)ibdesc32.sizedwords;
			ibdesc.ctrl = (unsigned int)ibdesc32.ctrl;

			ret = kgsl_cmdbatch_add_memobj(cmdbatch, &ibdesc);
			if (ret)
				goto done;

			uptr += sizeof(ibdesc32);
		}
	}
	if (synclist && numsyncs) {

		struct kgsl_cmd_syncpoint_compat sync32;
		struct kgsl_cmd_syncpoint sync;
		void __user *uptr = synclist;

		for (i = 0; i < numsyncs; i++) {
			memset(&sync32, 0, sizeof(sync32));

			if (copy_from_user(&sync32, uptr, sizeof(sync32)))
				return -EFAULT;

			sync.type = sync32.type;
			sync.priv = compat_ptr(sync32.priv);
			sync.size = (size_t)sync32.size;

			ret = kgsl_cmdbatch_add_sync(device, cmdbatch, &sync);
			if (ret)
				return ret;
			uptr += sizeof(sync32);
		}
	}

done:
	return ret;
}
/**
 * kgsl_cmdbatch_create_compat() - Compat helper to _kgsl_cmdbatch_create()
 * @device: Pointer to the KGSL device struct for the GPU
 * @flags: Flags passed in from the user command
 * @cmdlist: Pointer to the list of commands from the user. Should point to a
 * kgsl_ibdesc_compat struct
 * @numcmds: Number of commands in the list
 * @synclist: Pointer to the list of syncpoints from the user. Should point to
 * a kgsl_cmd_syncpoint_compat struct
 * @numsyncs: Number of syncpoints in the list
 *
 * This function is called from _kgsl_cmdbatch_create(), if the user process
 * submitting cmds is 32 bit, instead of executing rest of the function.
 * It is needed since we do multiple copy_from_user() calls which would
 * otherwise be copying user data into the wrongly sized/structured struct.
 */
int kgsl_cmdbatch_create_compat(struct kgsl_device *device, unsigned int flags,
			struct kgsl_cmdbatch *cmdbatch, void __user *cmdlist,
			unsigned int numcmds, void __user *synclist,
			unsigned int numsyncs)
{
	int ret = 0;
	struct kgsl_ibdesc_compat *cmdbatch_ibdesc;

	if (!(flags & KGSL_CONTEXT_SYNC)) {
		if (copy_from_user(cmdbatch_ibdesc, cmdlist,
			sizeof(struct kgsl_ibdesc_compat) * numcmds))
			return -EFAULT;

		cmdbatch->ibdesc->gpuaddr = (unsigned long)
						cmdbatch_ibdesc->gpuaddr;
		cmdbatch->ibdesc->sizedwords = (size_t)
						cmdbatch_ibdesc->sizedwords;
		cmdbatch->ibdesc->ctrl = cmdbatch_ibdesc->ctrl;
	}
	if (synclist && numsyncs) {

		struct kgsl_cmd_syncpoint_compat sync32;
		struct kgsl_cmd_syncpoint sync;
		void __user *uptr = synclist;
		int i;

		for (i = 0; i < numsyncs; i++) {
			memset(&sync32, 0, sizeof(sync32));

			if (copy_from_user(&sync32, uptr, sizeof(sync32)))
				return -EFAULT;

			sync.type = sync32.type;
			sync.priv = compat_ptr(sync32.priv);
			sync.size = (size_t)sync32.size;

			ret = kgsl_cmdbatch_add_sync(device, cmdbatch, &sync);
			if (ret)
				return ret;
			uptr += sizeof(sync32);
		}
	}
	return ret;
}