aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/main.c')
-rw-r--r--drivers/misc/mei/main.c106
1 files changed, 43 insertions, 63 deletions
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 80f9afcb1382..52635b063873 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -65,7 +65,7 @@ static int mei_open(struct inode *inode, struct file *file)
65 goto err_unlock; 65 goto err_unlock;
66 } 66 }
67 67
68 cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY); 68 cl = mei_cl_alloc_linked(dev);
69 if (IS_ERR(cl)) { 69 if (IS_ERR(cl)) {
70 err = PTR_ERR(cl); 70 err = PTR_ERR(cl);
71 goto err_unlock; 71 goto err_unlock;
@@ -159,27 +159,22 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
159 goto out; 159 goto out;
160 } 160 }
161 161
162 if (ubuf == NULL) {
163 rets = -EMSGSIZE;
164 goto out;
165 }
166
162 if (cl == &dev->iamthif_cl) { 167 if (cl == &dev->iamthif_cl) {
163 rets = mei_amthif_read(dev, file, ubuf, length, offset); 168 rets = mei_amthif_read(dev, file, ubuf, length, offset);
164 goto out; 169 goto out;
165 } 170 }
166 171
167 cb = mei_cl_read_cb(cl, file); 172 cb = mei_cl_read_cb(cl, file);
168 if (cb) { 173 if (cb)
169 /* read what left */ 174 goto copy_buffer;
170 if (cb->buf_idx > *offset) 175
171 goto copy_buffer; 176 if (*offset > 0)
172 /* offset is beyond buf_idx we have no more data return 0 */
173 if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
174 rets = 0;
175 goto free;
176 }
177 /* Offset needs to be cleaned for contiguous reads*/
178 if (cb->buf_idx == 0 && *offset > 0)
179 *offset = 0;
180 } else if (*offset > 0) {
181 *offset = 0; 177 *offset = 0;
182 }
183 178
184 err = mei_cl_read_start(cl, length, file); 179 err = mei_cl_read_start(cl, length, file);
185 if (err && err != -EBUSY) { 180 if (err && err != -EBUSY) {
@@ -214,11 +209,6 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
214 209
215 cb = mei_cl_read_cb(cl, file); 210 cb = mei_cl_read_cb(cl, file);
216 if (!cb) { 211 if (!cb) {
217 if (mei_cl_is_fixed_address(cl) && dev->allow_fixed_address) {
218 cb = mei_cl_read_cb(cl, NULL);
219 if (cb)
220 goto copy_buffer;
221 }
222 rets = 0; 212 rets = 0;
223 goto out; 213 goto out;
224 } 214 }
@@ -231,10 +221,10 @@ copy_buffer:
231 goto free; 221 goto free;
232 } 222 }
233 223
234 cl_dbg(dev, cl, "buf.size = %d buf.idx = %ld\n", 224 cl_dbg(dev, cl, "buf.size = %zu buf.idx = %zu offset = %lld\n",
235 cb->buf.size, cb->buf_idx); 225 cb->buf.size, cb->buf_idx, *offset);
236 if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) { 226 if (*offset >= cb->buf_idx) {
237 rets = -EMSGSIZE; 227 rets = 0;
238 goto free; 228 goto free;
239 } 229 }
240 230
@@ -250,11 +240,13 @@ copy_buffer:
250 240
251 rets = length; 241 rets = length;
252 *offset += length; 242 *offset += length;
253 if ((unsigned long)*offset < cb->buf_idx) 243 /* not all data was read, keep the cb */
244 if (*offset < cb->buf_idx)
254 goto out; 245 goto out;
255 246
256free: 247free:
257 mei_io_cb_free(cb); 248 mei_io_cb_free(cb);
249 *offset = 0;
258 250
259out: 251out:
260 cl_dbg(dev, cl, "end mei read rets = %d\n", rets); 252 cl_dbg(dev, cl, "end mei read rets = %d\n", rets);
@@ -275,9 +267,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
275 size_t length, loff_t *offset) 267 size_t length, loff_t *offset)
276{ 268{
277 struct mei_cl *cl = file->private_data; 269 struct mei_cl *cl = file->private_data;
278 struct mei_cl_cb *write_cb = NULL; 270 struct mei_cl_cb *cb;
279 struct mei_device *dev; 271 struct mei_device *dev;
280 unsigned long timeout = 0;
281 int rets; 272 int rets;
282 273
283 if (WARN_ON(!cl || !cl->dev)) 274 if (WARN_ON(!cl || !cl->dev))
@@ -313,52 +304,31 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
313 goto out; 304 goto out;
314 } 305 }
315 306
316 if (cl == &dev->iamthif_cl) {
317 write_cb = mei_amthif_find_read_list_entry(dev, file);
318
319 if (write_cb) {
320 timeout = write_cb->read_time +
321 mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
322
323 if (time_after(jiffies, timeout)) {
324 *offset = 0;
325 mei_io_cb_free(write_cb);
326 write_cb = NULL;
327 }
328 }
329 }
330
331 *offset = 0; 307 *offset = 0;
332 write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file); 308 cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file);
333 if (!write_cb) { 309 if (!cb) {
334 rets = -ENOMEM; 310 rets = -ENOMEM;
335 goto out; 311 goto out;
336 } 312 }
337 313
338 rets = copy_from_user(write_cb->buf.data, ubuf, length); 314 rets = copy_from_user(cb->buf.data, ubuf, length);
339 if (rets) { 315 if (rets) {
340 dev_dbg(dev->dev, "failed to copy data from userland\n"); 316 dev_dbg(dev->dev, "failed to copy data from userland\n");
341 rets = -EFAULT; 317 rets = -EFAULT;
318 mei_io_cb_free(cb);
342 goto out; 319 goto out;
343 } 320 }
344 321
345 if (cl == &dev->iamthif_cl) { 322 if (cl == &dev->iamthif_cl) {
346 rets = mei_amthif_write(cl, write_cb); 323 rets = mei_amthif_write(cl, cb);
347 324 if (!rets)
348 if (rets) { 325 rets = length;
349 dev_err(dev->dev, 326 goto out;
350 "amthif write failed with status = %d\n", rets);
351 goto out;
352 }
353 mutex_unlock(&dev->device_lock);
354 return length;
355 } 327 }
356 328
357 rets = mei_cl_write(cl, write_cb, false); 329 rets = mei_cl_write(cl, cb, false);
358out: 330out:
359 mutex_unlock(&dev->device_lock); 331 mutex_unlock(&dev->device_lock);
360 if (rets < 0)
361 mei_io_cb_free(write_cb);
362 return rets; 332 return rets;
363} 333}
364 334
@@ -393,12 +363,22 @@ static int mei_ioctl_connect_client(struct file *file,
393 363
394 /* find ME client we're trying to connect to */ 364 /* find ME client we're trying to connect to */
395 me_cl = mei_me_cl_by_uuid(dev, &data->in_client_uuid); 365 me_cl = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
396 if (!me_cl || 366 if (!me_cl) {
397 (me_cl->props.fixed_address && !dev->allow_fixed_address)) {
398 dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n", 367 dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n",
399 &data->in_client_uuid); 368 &data->in_client_uuid);
400 mei_me_cl_put(me_cl); 369 rets = -ENOTTY;
401 return -ENOTTY; 370 goto end;
371 }
372
373 if (me_cl->props.fixed_address) {
374 bool forbidden = dev->override_fixed_address ?
375 !dev->allow_fixed_address : !dev->hbm_f_fa_supported;
376 if (forbidden) {
377 dev_dbg(dev->dev, "Connection forbidden to FW Client UUID = %pUl\n",
378 &data->in_client_uuid);
379 rets = -ENOTTY;
380 goto end;
381 }
402 } 382 }
403 383
404 dev_dbg(dev->dev, "Connect to FW Client ID = %d\n", 384 dev_dbg(dev->dev, "Connect to FW Client ID = %d\n",
@@ -454,7 +434,7 @@ end:
454 * 434 *
455 * Return: 0 on success , <0 on error 435 * Return: 0 on success , <0 on error
456 */ 436 */
457static int mei_ioctl_client_notify_request(struct file *file, u32 request) 437static int mei_ioctl_client_notify_request(const struct file *file, u32 request)
458{ 438{
459 struct mei_cl *cl = file->private_data; 439 struct mei_cl *cl = file->private_data;
460 440
@@ -473,7 +453,7 @@ static int mei_ioctl_client_notify_request(struct file *file, u32 request)
473 * 453 *
474 * Return: 0 on success , <0 on error 454 * Return: 0 on success , <0 on error
475 */ 455 */
476static int mei_ioctl_client_notify_get(struct file *file, u32 *notify_get) 456static int mei_ioctl_client_notify_get(const struct file *file, u32 *notify_get)
477{ 457{
478 struct mei_cl *cl = file->private_data; 458 struct mei_cl *cl = file->private_data;
479 bool notify_ev; 459 bool notify_ev;