Skip to content
Permalink
Browse files
fsi: sbefifo: implement FSI_SBEFIFO_READ_TIMEOUT ioctl
FSI_SBEFIFO_READ_TIMEOUT ioctl sets the read timeout (in seconds) for
the response to *the next* chip-op sent to sbe.  The timeout value is
reset to default after the chip-op.  The timeout affects only the read()
operation on sbefifo device fd.

Signed-off-by: Amitay Isaacs <amitay@ozlabs.org>
  • Loading branch information
amitay authored and intel-lab-lkp committed Dec 15, 2021
1 parent 511f0bb commit abe81bc06079f76e9a9f4ebe6cc0a963ee5b6985
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
@@ -32,6 +32,8 @@
#include <linux/vmalloc.h>
#include <linux/mm.h>

#include <uapi/linux/fsi.h>

/*
* The SBEFIFO is a pipe-like FSI device for communicating with
* the self boot engine on POWER processors.
@@ -134,6 +136,7 @@ struct sbefifo_user {
void *cmd_page;
void *pending_cmd;
size_t pending_len;
uint32_t read_timeout_ms;
};

static DEFINE_MUTEX(sbefifo_ffdc_mutex);
@@ -796,6 +799,7 @@ static int sbefifo_user_open(struct inode *inode, struct file *file)
return -ENOMEM;
}
mutex_init(&user->file_lock);
user->read_timeout_ms = SBEFIFO_TIMEOUT_START_RSP;

return 0;
}
@@ -838,7 +842,11 @@ static ssize_t sbefifo_user_read(struct file *file, char __user *buf,
rc = mutex_lock_interruptible(&sbefifo->lock);
if (rc)
goto bail;
sbefifo->timeout_start_rsp_ms = user->read_timeout_ms;
rc = __sbefifo_submit(sbefifo, user->pending_cmd, cmd_len, &resp_iter);
/* Reset the read timeout after a single chip-op */
sbefifo->timeout_start_rsp_ms = SBEFIFO_TIMEOUT_START_RSP;
user->read_timeout_ms = SBEFIFO_TIMEOUT_START_RSP;
mutex_unlock(&sbefifo->lock);
if (rc < 0)
goto bail;
@@ -847,6 +855,7 @@ static ssize_t sbefifo_user_read(struct file *file, char __user *buf,
rc = len - iov_iter_count(&resp_iter);
bail:
sbefifo_release_command(user);
user->read_timeout_ms = 0;
mutex_unlock(&user->file_lock);
return rc;
}
@@ -928,12 +937,45 @@ static int sbefifo_user_release(struct inode *inode, struct file *file)
return 0;
}

static int sbefifo_read_timeout(struct sbefifo_user *user, void __user **argp)
{
uint32_t timeout;

if (get_user(timeout, (__u32 __user *)argp))
return -EFAULT;
if (timeout < 10 || timeout > 120)
return -EINVAL;

user->read_timeout_ms = timeout * 1000; /* user timeout is in sec */
return 0;
}

static long sbefifo_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct sbefifo_user *user = file->private_data;
void __user **argp = (void __user *)arg;
int rc = -ENOTTY;

if (!user)
return -EINVAL;

mutex_lock(&user->file_lock);
switch (cmd) {
case FSI_SBEFIFO_READ_TIMEOUT:
rc = sbefifo_read_timeout(user, argp);
break;
}
mutex_unlock(&user->file_lock);
return rc;
}

static const struct file_operations sbefifo_fops = {
.owner = THIS_MODULE,
.open = sbefifo_user_open,
.read = sbefifo_user_read,
.write = sbefifo_user_write,
.release = sbefifo_user_release,
.unlocked_ioctl = sbefifo_user_ioctl,
};

static void sbefifo_free(struct device *dev)
@@ -55,4 +55,10 @@ struct scom_access {
#define FSI_SCOM_WRITE _IOWR('s', 0x02, struct scom_access)
#define FSI_SCOM_RESET _IOW('s', 0x03, __u32)

/*
* /dev/sbefifo* ioctl interface
*/

#define FSI_SBEFIFO_READ_TIMEOUT _IOW('s', 0x00, __u32)

#endif /* _UAPI_LINUX_FSI_H */

0 comments on commit abe81bc

Please sign in to comment.