For some of the chip-ops where sbe needs to collect trace information,
sbe can take a long time (>30s) to respond. Currently these chip-ops
will timeout as the start of response timeout defaults to 10s.
Instead of default value, use specified value. The require timeout
value will be set using ioctl.
Signed-off-by: Amitay Isaacs <[email protected]>
---
drivers/fsi/fsi-sbefifo.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
index 52328adef643..9188161f440c 100644
--- a/drivers/fsi/fsi-sbefifo.c
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -125,6 +125,7 @@ struct sbefifo {
bool dead;
bool async_ffdc;
bool timed_out;
+ uint32_t timeout_start_rsp_ms;
};
struct sbefifo_user {
@@ -549,7 +550,7 @@ static int sbefifo_read_response(struct sbefifo *sbefifo, struct iov_iter *respo
dev_vdbg(dev, "reading response, buflen = %zd\n", iov_iter_count(response));
- timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_START_RSP);
+ timeout = msecs_to_jiffies(sbefifo->timeout_start_rsp_ms);
for (;;) {
/* Grab FIFO status (this will handle parity errors) */
rc = sbefifo_wait(sbefifo, false, &status, timeout);
@@ -972,6 +973,7 @@ static int sbefifo_probe(struct device *dev)
sbefifo->fsi_dev = fsi_dev;
dev_set_drvdata(dev, sbefifo);
mutex_init(&sbefifo->lock);
+ sbefifo->timeout_start_rsp_ms = SBEFIFO_TIMEOUT_START_RSP;
/*
* Try cleaning up the FIFO. If this fails, we still register the
--
2.33.1
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 <[email protected]>
---
drivers/fsi/fsi-sbefifo.c | 42 +++++++++++++++++++++++++++++++++++++++
include/uapi/linux/fsi.h | 6 ++++++
2 files changed, 48 insertions(+)
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
index 9188161f440c..b2654b143b85 100644
--- a/drivers/fsi/fsi-sbefifo.c
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -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)
diff --git a/include/uapi/linux/fsi.h b/include/uapi/linux/fsi.h
index da577ecd90e7..3e00874ace22 100644
--- a/include/uapi/linux/fsi.h
+++ b/include/uapi/linux/fsi.h
@@ -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 */
--
2.33.1
On Wed, 15 Dec 2021 at 00:58, Amitay Isaacs <[email protected]> wrote:
>
> 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.
Makes sense to me.
Lets see if Greg or Andrew will review the icotl interface for us.
Reviewed-by: Joel Stanley <[email protected]>
>
> Signed-off-by: Amitay Isaacs <[email protected]>
> ---
> drivers/fsi/fsi-sbefifo.c | 42 +++++++++++++++++++++++++++++++++++++++
> include/uapi/linux/fsi.h | 6 ++++++
> 2 files changed, 48 insertions(+)
>
> diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
> index 9188161f440c..b2654b143b85 100644
> --- a/drivers/fsi/fsi-sbefifo.c
> +++ b/drivers/fsi/fsi-sbefifo.c
> @@ -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)
> diff --git a/include/uapi/linux/fsi.h b/include/uapi/linux/fsi.h
> index da577ecd90e7..3e00874ace22 100644
> --- a/include/uapi/linux/fsi.h
> +++ b/include/uapi/linux/fsi.h
> @@ -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 */
> --
> 2.33.1
>
Hi Amitay,
On Wed, 15 Dec 2021, at 11:28, Amitay Isaacs wrote:
> 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.
For the user? Why reset it automatically? To avoid unexpected surprises
in existing code?
> The timeout affects only the read()
> operation on sbefifo device fd.
>
> Signed-off-by: Amitay Isaacs <[email protected]>
> ---
> drivers/fsi/fsi-sbefifo.c | 42 +++++++++++++++++++++++++++++++++++++++
> include/uapi/linux/fsi.h | 6 ++++++
> 2 files changed, 48 insertions(+)
>
> diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
> index 9188161f440c..b2654b143b85 100644
> --- a/drivers/fsi/fsi-sbefifo.c
> +++ b/drivers/fsi/fsi-sbefifo.c
> @@ -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;
I guess I was querying this one
> 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))
Hmm
> + 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;
Why are we doing strange things with the pointer types?
Andrew
> + 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)
> diff --git a/include/uapi/linux/fsi.h b/include/uapi/linux/fsi.h
> index da577ecd90e7..3e00874ace22 100644
> --- a/include/uapi/linux/fsi.h
> +++ b/include/uapi/linux/fsi.h
> @@ -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 */
> --
> 2.33.1
On Wed, Dec 15, 2021 at 11:58:33AM +1100, Amitay Isaacs wrote:
> 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 <[email protected]>
> ---
> drivers/fsi/fsi-sbefifo.c | 42 +++++++++++++++++++++++++++++++++++++++
> include/uapi/linux/fsi.h | 6 ++++++
> 2 files changed, 48 insertions(+)
>
> diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
> index 9188161f440c..b2654b143b85 100644
> --- a/drivers/fsi/fsi-sbefifo.c
> +++ b/drivers/fsi/fsi-sbefifo.c
> @@ -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;
u32 please. uint32_t is a userspace thing.
> };
>
> 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;
u32
> +
> + 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;
> +}
Why do you have to have an ioctl for a single thing like this?
> +
> 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)
> diff --git a/include/uapi/linux/fsi.h b/include/uapi/linux/fsi.h
> index da577ecd90e7..3e00874ace22 100644
> --- a/include/uapi/linux/fsi.h
> +++ b/include/uapi/linux/fsi.h
> @@ -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)
Where have you documented this new user/kernel api?
And why not just use a sysfs file for something like this?
thanks,
greg k-h
Hi Andrew,
On Wed, 2021-12-15 at 16:13 +1030, Andrew Jeffery wrote:
> Hi Amitay,
>
> On Wed, 15 Dec 2021, at 11:28, Amitay Isaacs wrote:
> > 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.
>
> For the user? Why reset it automatically? To avoid unexpected
> surprises in existing code?
Ideally I would prefer the timeout as an argument for the read() call,
so it's specific to that read call and nothing else. Of course, this
simplifies the user-space code that needs to issue only a single ioctl
before the "long" chip-ops.
I am fine with using the ioctl to just set the timeout value also.
>
> > The timeout affects only the read()
> > operation on sbefifo device fd.
> >
> > Signed-off-by: Amitay Isaacs <[email protected]>
> > ---
> > drivers/fsi/fsi-sbefifo.c | 42
> > +++++++++++++++++++++++++++++++++++++++
> > include/uapi/linux/fsi.h | 6 ++++++
> > 2 files changed, 48 insertions(+)
> >
> > diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
> > index 9188161f440c..b2654b143b85 100644
> > --- a/drivers/fsi/fsi-sbefifo.c
> > +++ b/drivers/fsi/fsi-sbefifo.c
> > @@ -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;
>
> I guess I was querying this one
>
> > 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))
>
> Hmm
>
> > + 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;
>
> Why are we doing strange things with the pointer types?
That's what the ioctl implementation for fsi does. (Monkey see, monkey
copy!) :-)
>
> Andrew
>
> > + 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)
> > diff --git a/include/uapi/linux/fsi.h b/include/uapi/linux/fsi.h
> > index da577ecd90e7..3e00874ace22 100644
> > --- a/include/uapi/linux/fsi.h
> > +++ b/include/uapi/linux/fsi.h
> > @@ -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 */
> > --
> > 2.33.1
Amitay.
--
There will always be rocks in the road ahead of you.
They will be stumbling blocks or stepping stones;
It all depends on how you use them
On Wed, 2021-12-15 at 06:59 +0100, Greg KH wrote:
> On Wed, Dec 15, 2021 at 11:58:33AM +1100, Amitay Isaacs wrote:
> > 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 <[email protected]>
> > ---
> > drivers/fsi/fsi-sbefifo.c | 42
> > +++++++++++++++++++++++++++++++++++++++
> > include/uapi/linux/fsi.h | 6 ++++++
> > 2 files changed, 48 insertions(+)
> >
> > diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
> > index 9188161f440c..b2654b143b85 100644
> > --- a/drivers/fsi/fsi-sbefifo.c
> > +++ b/drivers/fsi/fsi-sbefifo.c
> > @@ -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;
>
> u32 please. uint32_t is a userspace thing.
Sure thing.
>
> > };
> >
> > 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;
>
> u32
>
> > +
> > + 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;
> > +}
>
> Why do you have to have an ioctl for a single thing like this?
This timeout needs to be set for only certain write/read operations
(referred as sbe chip-ops) done via open fd for sbefifo device. There
can be multiple simultaneous users of the device, and the timeout
should only be applied to specific chip-ops as user requests.
>
> > +
> > 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)
> > diff --git a/include/uapi/linux/fsi.h b/include/uapi/linux/fsi.h
> > index da577ecd90e7..3e00874ace22 100644
> > --- a/include/uapi/linux/fsi.h
> > +++ b/include/uapi/linux/fsi.h
> > @@ -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)
>
> Where have you documented this new user/kernel api?
What's the best location to add the information? I would prefer to add
this information along with the FSI ioctl, but could not find it in
Documentation/.
>
> And why not just use a sysfs file for something like this?
>
I guess sysfs interface would be useful for setting a global property,
rather than a parameter affecting individual operation.
>
> thanks,
>
> greg k-h
Thanks.
Amitay.
--
I know you believe you understand what you think I wrote. But I am not
sure you realise that what you read is not what I meant.
Hi Amitay,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on linux/master]
[also build test WARNING on linus/master v5.16-rc5 next-20211214]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Amitay-Isaacs/fsi-sbefifo-Use-specified-value-of-start-of-response-timeout/20211215-090038
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 136057256686de39cc3a07c2e39ef6bc43003ff6
config: h8300-randconfig-s032-20211214 (https://download.01.org/0day-ci/archive/20211215/[email protected]/config)
compiler: h8300-linux-gcc (GCC) 11.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.4-dirty
# https://github.com/0day-ci/linux/commit/abe81bc06079f76e9a9f4ebe6cc0a963ee5b6985
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Amitay-Isaacs/fsi-sbefifo-Use-specified-value-of-start-of-response-timeout/20211215-090038
git checkout abe81bc06079f76e9a9f4ebe6cc0a963ee5b6985
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=h8300 SHELL=/bin/bash drivers/fsi/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>
sparse warnings: (new ones prefixed by >>)
>> drivers/fsi/fsi-sbefifo.c:956:31: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected void [noderef] __user **argp @@ got void [noderef] __user * @@
drivers/fsi/fsi-sbefifo.c:956:31: sparse: expected void [noderef] __user **argp
drivers/fsi/fsi-sbefifo.c:956:31: sparse: got void [noderef] __user *
vim +956 drivers/fsi/fsi-sbefifo.c
952
953 static long sbefifo_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
954 {
955 struct sbefifo_user *user = file->private_data;
> 956 void __user **argp = (void __user *)arg;
957 int rc = -ENOTTY;
958
959 if (!user)
960 return -EINVAL;
961
962 mutex_lock(&user->file_lock);
963 switch (cmd) {
964 case FSI_SBEFIFO_READ_TIMEOUT:
965 rc = sbefifo_read_timeout(user, argp);
966 break;
967 }
968 mutex_unlock(&user->file_lock);
969 return rc;
970 }
971
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]