From 9479d8f12efc845faca4bb1aef9b6e63799a7e5c Mon Sep 17 00:00:00 2001 From: "Arun P. Mohanan" Date: Wed, 18 Mar 2020 08:34:43 +0530 Subject: [PATCH] Add poll fops in eSPI driver Modify eSPI driver to support poll fops. Signed-off-by: Arun P. Mohanan --- drivers/misc/aspeed-espi-slave.c | 85 +++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 24 deletions(-) diff --git a/drivers/misc/aspeed-espi-slave.c b/drivers/misc/aspeed-espi-slave.c index 87bc81948694..cb8ed585c69f 100644 --- a/drivers/misc/aspeed-espi-slave.c +++ b/drivers/misc/aspeed-espi-slave.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,7 @@ struct aspeed_espi { spinlock_t pltrstn_lock; /* for PLTRST_N signal sampling */ wait_queue_head_t pltrstn_waitq; char pltrstn; + bool pltrstn_in_avail; }; static void aspeed_espi_sys_event(struct aspeed_espi *priv) @@ -127,7 +129,10 @@ static void aspeed_espi_sys_event(struct aspeed_espi *priv) dev_dbg(priv->dev, "SYSEVT_OOB_RST_WARN: acked\n"); } if (sts & ASPEED_ESPI_SYSEVT_PLTRSTN || priv->pltrstn == 'U') { + spin_lock(&priv->pltrstn_lock); priv->pltrstn = (evt & ASPEED_ESPI_SYSEVT_PLTRSTN) ? '1' : '0'; + priv->pltrstn_in_avail = true; + spin_unlock(&priv->pltrstn_lock); wake_up_interruptible(&priv->pltrstn_waitq); dev_dbg(priv->dev, "SYSEVT_PLTRSTN: %c\n", priv->pltrstn); } @@ -269,6 +274,8 @@ static int aspeed_espi_pltrstn_open(struct inode *inode, struct file *filp) { if ((filp->f_flags & O_ACCMODE) != O_RDONLY) return -EACCES; + struct aspeed_espi *priv = to_aspeed_espi(filp); + priv->pltrstn_in_avail = true ; /*Setting true returns first data after file open*/ return 0; } @@ -284,41 +291,71 @@ static ssize_t aspeed_espi_pltrstn_read(struct file *filp, char __user *buf, spin_lock_irqsave(&priv->pltrstn_lock, flags); - add_wait_queue(&priv->pltrstn_waitq, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - old_sample = priv->pltrstn; - - do { - char new_sample = priv->pltrstn; - - if (filp->f_flags & O_NONBLOCK || old_sample != new_sample) { - ret = put_user(new_sample, (unsigned long __user *)buf); - if (!ret) - ret = sizeof(new_sample); - } else if (signal_pending(current)) { - ret = -ERESTARTSYS; + if (filp->f_flags & O_NONBLOCK) { + if (!priv->pltrstn_in_avail) { + ret = -EAGAIN; + goto out_unlock; } - - if (!ret) { - spin_unlock_irqrestore(&priv->pltrstn_lock, flags); - schedule(); - spin_lock_irqsave(&priv->pltrstn_lock, flags); + char data = priv->pltrstn; + ret = put_user(data, (unsigned long __user *)buf); + if (!ret){ + ret = sizeof(data); + } else{ + ret = -EAGAIN; } - } while (!ret); - - remove_wait_queue(&priv->pltrstn_waitq, &wait); - set_current_state(TASK_RUNNING); - + priv->pltrstn_in_avail = false; + } else { + add_wait_queue(&priv->pltrstn_waitq, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + old_sample = priv->pltrstn; + + do { + char new_sample = priv->pltrstn; + + if (old_sample != new_sample) { + ret = put_user(new_sample, + (unsigned long __user *)buf); + if (!ret) + ret = sizeof(new_sample); + } else if (signal_pending(current)) { + ret = -ERESTARTSYS; + } + + if (!ret) { + spin_unlock_irqrestore(&priv->pltrstn_lock, + flags); + schedule(); + spin_lock_irqsave(&priv->pltrstn_lock, flags); + } + } while (!ret); + + remove_wait_queue(&priv->pltrstn_waitq, &wait); + set_current_state(TASK_RUNNING); + } +out_unlock: spin_unlock_irqrestore(&priv->pltrstn_lock, flags); return ret; } +static unsigned int aspeed_espi_pltrstn_poll(struct file *file, + poll_table *wait) +{ + struct aspeed_espi *priv = to_aspeed_espi(file); + unsigned int mask = 0; + poll_wait(file, &priv->pltrstn_waitq, wait); + + if (priv->pltrstn_in_avail) + mask |= POLLIN; + return mask; +} + static const struct file_operations aspeed_espi_pltrstn_fops = { .owner = THIS_MODULE, .open = aspeed_espi_pltrstn_open, .read = aspeed_espi_pltrstn_read, + .poll = aspeed_espi_pltrstn_poll, }; static const struct regmap_config aspeed_espi_regmap_cfg = { -- 2.17.1