summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0101-Add-poll-fops-in-eSPI-driver.patch
blob: b4118e169eaa017af6339693dd58d40baf701eb1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
From 9479d8f12efc845faca4bb1aef9b6e63799a7e5c Mon Sep 17 00:00:00 2001
From: "Arun P. Mohanan" <arun.p.m@linux.intel.com>
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 <arun.p.m@linux.intel.com>
---
 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 <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/poll.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 #include <linux/sched/signal.h>
@@ -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