aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2016-07-25 18:06:06 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-08-30 08:39:42 -0400
commitff1586a7ea57a4758a3f10ad7c9cdb26edcbd7f3 (patch)
treeb687e5062e85b54af6bd18c53c563f65507d8075 /drivers/misc
parent3030dc056459439d756d81a920e135893076a348 (diff)
mei: enqueue consecutive reads
The FW supports only one pending read per host client, in order to support issuing of consecutive reads the driver queues read requests internally and send them to the firmware after pending one has completed. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/interrupt.c3
-rw-r--r--drivers/misc/mei/main.c39
2 files changed, 22 insertions, 20 deletions
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 36382d782e20..bf745e03f21e 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -209,6 +209,9 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
209 int slots; 209 int slots;
210 int ret; 210 int ret;
211 211
212 if (!list_empty(&cl->rd_pending))
213 return 0;
214
212 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control)); 215 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
213 slots = mei_hbuf_empty_slots(dev); 216 slots = mei_hbuf_empty_slots(dev);
214 217
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index d698ba32357c..650061b6ab9b 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -139,9 +139,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
139 struct mei_cl *cl = file->private_data; 139 struct mei_cl *cl = file->private_data;
140 struct mei_device *dev; 140 struct mei_device *dev;
141 struct mei_cl_cb *cb = NULL; 141 struct mei_cl_cb *cb = NULL;
142 bool nonblock = !!(file->f_flags & O_NONBLOCK);
142 int rets; 143 int rets;
143 int err;
144
145 144
146 if (WARN_ON(!cl || !cl->dev)) 145 if (WARN_ON(!cl || !cl->dev))
147 return -ENODEV; 146 return -ENODEV;
@@ -177,25 +176,29 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
177 if (*offset > 0) 176 if (*offset > 0)
178 *offset = 0; 177 *offset = 0;
179 178
180 err = mei_cl_read_start(cl, length, file); 179 rets = mei_cl_read_start(cl, length, file);
181 if (err && err != -EBUSY) { 180 if (rets && rets != -EBUSY) {
182 cl_dbg(dev, cl, "mei start read failure status = %d\n", err); 181 cl_dbg(dev, cl, "mei start read failure status = %d\n", rets);
183 rets = err;
184 goto out; 182 goto out;
185 } 183 }
186 184
187 /* synchronized under device mutex */ 185 if (nonblock) {
188 if (!waitqueue_active(&cl->rx_wait)) { 186 rets = -EAGAIN;
189 if (file->f_flags & O_NONBLOCK) { 187 goto out;
190 rets = -EAGAIN; 188 }
191 goto out; 189
192 } 190 if (rets == -EBUSY &&
191 !mei_cl_enqueue_ctrl_wr_cb(cl, length, MEI_FOP_READ, file)) {
192 rets = -ENOMEM;
193 goto out;
194 }
193 195
196 do {
194 mutex_unlock(&dev->device_lock); 197 mutex_unlock(&dev->device_lock);
195 198
196 if (wait_event_interruptible(cl->rx_wait, 199 if (wait_event_interruptible(cl->rx_wait,
197 (!list_empty(&cl->rd_completed)) || 200 (!list_empty(&cl->rd_completed)) ||
198 (!mei_cl_is_connected(cl)))) { 201 (!mei_cl_is_connected(cl)))) {
199 202
200 if (signal_pending(current)) 203 if (signal_pending(current))
201 return -EINTR; 204 return -EINTR;
@@ -207,13 +210,9 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
207 rets = -ENODEV; 210 rets = -ENODEV;
208 goto out; 211 goto out;
209 } 212 }
210 }
211 213
212 cb = mei_cl_read_cb(cl, file); 214 cb = mei_cl_read_cb(cl, file);
213 if (!cb) { 215 } while (!cb);
214 rets = 0;
215 goto out;
216 }
217 216
218copy_buffer: 217copy_buffer:
219 /* now copy the data to user space */ 218 /* now copy the data to user space */