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;
}