in fsi-sbefifo.c [802:851]
static ssize_t sbefifo_user_read(struct file *file, char __user *buf,
size_t len, loff_t *offset)
{
struct sbefifo_user *user = file->private_data;
struct sbefifo *sbefifo;
struct iov_iter resp_iter;
struct iovec resp_iov;
size_t cmd_len;
int rc;
if (!user)
return -EINVAL;
sbefifo = user->sbefifo;
if (len & 3)
return -EINVAL;
mutex_lock(&user->file_lock);
/* Cronus relies on -EAGAIN after a short read */
if (user->pending_len == 0) {
rc = -EAGAIN;
goto bail;
}
if (user->pending_len < 8) {
rc = -EINVAL;
goto bail;
}
cmd_len = user->pending_len >> 2;
/* Prepare iov iterator */
resp_iov.iov_base = buf;
resp_iov.iov_len = len;
iov_iter_init(&resp_iter, WRITE, &resp_iov, 1, len);
/* Perform the command */
rc = mutex_lock_interruptible(&sbefifo->lock);
if (rc)
goto bail;
rc = __sbefifo_submit(sbefifo, user->pending_cmd, cmd_len, &resp_iter);
mutex_unlock(&sbefifo->lock);
if (rc < 0)
goto bail;
/* Extract the response length */
rc = len - iov_iter_count(&resp_iter);
bail:
sbefifo_release_command(user);
mutex_unlock(&user->file_lock);
return rc;
}