static ssize_t smu_write()

in smu.c [1115:1170]


static ssize_t smu_write(struct file *file, const char __user *buf,
			 size_t count, loff_t *ppos)
{
	struct smu_private *pp = file->private_data;
	unsigned long flags;
	struct smu_user_cmd_hdr hdr;
	int rc = 0;

	if (pp->busy)
		return -EBUSY;
	else if (copy_from_user(&hdr, buf, sizeof(hdr)))
		return -EFAULT;
	else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) {
		pp->mode = smu_file_events;
		return 0;
	} else if (hdr.cmdtype == SMU_CMDTYPE_GET_PARTITION) {
		const struct smu_sdbp_header *part;
		part = __smu_get_sdb_partition(hdr.cmd, NULL, 1);
		if (part == NULL)
			return -EINVAL;
		else if (IS_ERR(part))
			return PTR_ERR(part);
		return 0;
	} else if (hdr.cmdtype != SMU_CMDTYPE_SMU)
		return -EINVAL;
	else if (pp->mode != smu_file_commands)
		return -EBADFD;
	else if (hdr.data_len > SMU_MAX_DATA)
		return -EINVAL;

	spin_lock_irqsave(&pp->lock, flags);
	if (pp->busy) {
		spin_unlock_irqrestore(&pp->lock, flags);
		return -EBUSY;
	}
	pp->busy = 1;
	pp->cmd.status = 1;
	spin_unlock_irqrestore(&pp->lock, flags);

	if (copy_from_user(pp->buffer, buf + sizeof(hdr), hdr.data_len)) {
		pp->busy = 0;
		return -EFAULT;
	}

	pp->cmd.cmd = hdr.cmd;
	pp->cmd.data_len = hdr.data_len;
	pp->cmd.reply_len = SMU_MAX_DATA;
	pp->cmd.data_buf = pp->buffer;
	pp->cmd.reply_buf = pp->buffer;
	pp->cmd.done = smu_user_cmd_done;
	pp->cmd.misc = pp;
	rc = smu_queue_cmd(&pp->cmd);
	if (rc < 0)
		return rc;
	return count;
}