aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2013-04-08 14:56:37 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-04-08 19:55:57 -0400
commit4234a6deb5ab04e50cfd6d72761345727bd2de21 (patch)
tree6da543ec16e78959e5a05055d4b6cee393d2ad47 /drivers/misc
parent606f34ad124faeeb77830d7fdfc513084566d2ba (diff)
mei: add mei_cl_write function
consolidate write code to a specific me client in mei_cl_write function the function is called from mei device write handler and from mei_cl bus send function 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/bus.c103
-rw-r--r--drivers/misc/mei/client.c105
-rw-r--r--drivers/misc/mei/client.h7
-rw-r--r--drivers/misc/mei/main.c83
-rw-r--r--drivers/misc/mei/mei_dev.h6
5 files changed, 146 insertions, 158 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 8dbcb1516dc6..6badfa1110e9 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -226,112 +226,47 @@ static int ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
226 bool blocking) 226 bool blocking)
227{ 227{
228 struct mei_device *dev; 228 struct mei_device *dev;
229 struct mei_msg_hdr mei_hdr;
230 struct mei_cl_cb *cb; 229 struct mei_cl_cb *cb;
231 int me_cl_id, err; 230 int id;
231 int rets;
232 232
233 if (WARN_ON(!cl || !cl->dev)) 233 if (WARN_ON(!cl || !cl->dev))
234 return -ENODEV; 234 return -ENODEV;
235 235
236 dev = cl->dev;
237
236 if (cl->state != MEI_FILE_CONNECTED) 238 if (cl->state != MEI_FILE_CONNECTED)
237 return -ENODEV; 239 return -ENODEV;
238 240
241 /* Check if we have an ME client device */
242 id = mei_me_cl_by_id(dev, cl->me_client_id);
243 if (id < 0)
244 return -ENODEV;
245
246 if (length > dev->me_clients[id].props.max_msg_length)
247 return -EINVAL;
248
239 cb = mei_io_cb_init(cl, NULL); 249 cb = mei_io_cb_init(cl, NULL);
240 if (!cb) 250 if (!cb)
241 return -ENOMEM; 251 return -ENOMEM;
242 252
243 err = mei_io_cb_alloc_req_buf(cb, length); 253 rets = mei_io_cb_alloc_req_buf(cb, length);
244 if (err < 0) { 254 if (rets < 0) {
245 mei_io_cb_free(cb); 255 mei_io_cb_free(cb);
246 return err; 256 return rets;
247 } 257 }
248 258
249 memcpy(cb->request_buffer.data, buf, length); 259 memcpy(cb->request_buffer.data, buf, length);
250 cb->fop_type = MEI_FOP_WRITE;
251
252 dev = cl->dev;
253 260
254 mutex_lock(&dev->device_lock); 261 mutex_lock(&dev->device_lock);
255 262
256 /* Check if we have an ME client device */ 263 rets = mei_cl_write(cl, cb, blocking);
257 me_cl_id = mei_me_cl_by_id(dev, cl->me_client_id);
258 if (me_cl_id == dev->me_clients_num) {
259 err = -ENODEV;
260 goto out_err;
261 }
262
263 if (length > dev->me_clients[me_cl_id].props.max_msg_length) {
264 err = -EINVAL;
265 goto out_err;
266 }
267
268 err = mei_cl_flow_ctrl_creds(cl);
269 if (err < 0)
270 goto out_err;
271
272 /* Host buffer is not ready, we queue the request */
273 if (err == 0 || !dev->hbuf_is_ready) {
274 cb->buf_idx = 0;
275 mei_hdr.msg_complete = 0;
276 cl->writing_state = MEI_WRITING;
277
278 goto out;
279 }
280
281 dev->hbuf_is_ready = false;
282
283 /* Check for a maximum length */
284 if (length > mei_hbuf_max_len(dev)) {
285 mei_hdr.length = mei_hbuf_max_len(dev);
286 mei_hdr.msg_complete = 0;
287 } else {
288 mei_hdr.length = length;
289 mei_hdr.msg_complete = 1;
290 }
291
292 mei_hdr.host_addr = cl->host_client_id;
293 mei_hdr.me_addr = cl->me_client_id;
294 mei_hdr.reserved = 0;
295
296 if (mei_write_message(dev, &mei_hdr, buf)) {
297 err = -EIO;
298 goto out_err;
299 }
300
301 cl->writing_state = MEI_WRITING;
302 cb->buf_idx = mei_hdr.length;
303
304out:
305 if (mei_hdr.msg_complete) {
306 if (mei_cl_flow_ctrl_reduce(cl)) {
307 err = -ENODEV;
308 goto out_err;
309 }
310 list_add_tail(&cb->list, &dev->write_waiting_list.list);
311 } else {
312 list_add_tail(&cb->list, &dev->write_list.list);
313 }
314 264
315 mutex_unlock(&dev->device_lock); 265 mutex_unlock(&dev->device_lock);
266 if (rets < 0)
267 mei_io_cb_free(cb);
316 268
317 if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) { 269 return rets;
318 if (wait_event_interruptible(cl->tx_wait,
319 cl->writing_state == MEI_WRITE_COMPLETE)) {
320 if (signal_pending(current))
321 err = -EINTR;
322 err = -ERESTARTSYS;
323 mutex_lock(&dev->device_lock);
324 goto out_err;
325 }
326 }
327
328 return mei_hdr.length;
329
330out_err:
331 mutex_unlock(&dev->device_lock);
332 mei_io_cb_free(cb);
333
334 return err;
335} 270}
336 271
337int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) 272int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index e14397b09187..ecadd0053ba9 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -678,6 +678,111 @@ err:
678} 678}
679 679
680/** 680/**
681 * mei_cl_write - submit a write cb to mei device
682 assumes device_lock is locked
683 *
684 * @cl: host client
685 * @cl: write callback with filled data
686 *
687 * returns numbe of bytes sent on success, <0 on failure.
688 */
689int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
690{
691 struct mei_device *dev;
692 struct mei_msg_data *buf;
693 struct mei_msg_hdr mei_hdr;
694 int rets;
695
696
697 if (WARN_ON(!cl || !cl->dev))
698 return -ENODEV;
699
700 if (WARN_ON(!cb))
701 return -EINVAL;
702
703 dev = cl->dev;
704
705
706 buf = &cb->request_buffer;
707
708 dev_dbg(&dev->pdev->dev, "mei_cl_write %d\n", buf->size);
709
710
711 cb->fop_type = MEI_FOP_WRITE;
712
713 rets = mei_cl_flow_ctrl_creds(cl);
714 if (rets < 0)
715 goto err;
716
717 /* Host buffer is not ready, we queue the request */
718 if (rets == 0 || !dev->hbuf_is_ready) {
719 cb->buf_idx = 0;
720 /* unseting complete will enqueue the cb for write */
721 mei_hdr.msg_complete = 0;
722 cl->writing_state = MEI_WRITING;
723 rets = buf->size;
724 goto out;
725 }
726
727 dev->hbuf_is_ready = false;
728
729 /* Check for a maximum length */
730 if (buf->size > mei_hbuf_max_len(dev)) {
731 mei_hdr.length = mei_hbuf_max_len(dev);
732 mei_hdr.msg_complete = 0;
733 } else {
734 mei_hdr.length = buf->size;
735 mei_hdr.msg_complete = 1;
736 }
737
738 mei_hdr.host_addr = cl->host_client_id;
739 mei_hdr.me_addr = cl->me_client_id;
740 mei_hdr.reserved = 0;
741
742 dev_dbg(&dev->pdev->dev, "write " MEI_HDR_FMT "\n",
743 MEI_HDR_PRM(&mei_hdr));
744
745
746 if (mei_write_message(dev, &mei_hdr, buf->data)) {
747 rets = -EIO;
748 goto err;
749 }
750
751 cl->writing_state = MEI_WRITING;
752 cb->buf_idx = mei_hdr.length;
753
754 rets = buf->size;
755out:
756 if (mei_hdr.msg_complete) {
757 if (mei_cl_flow_ctrl_reduce(cl)) {
758 rets = -ENODEV;
759 goto err;
760 }
761 list_add_tail(&cb->list, &dev->write_waiting_list.list);
762 } else {
763 list_add_tail(&cb->list, &dev->write_list.list);
764 }
765
766
767 if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {
768
769 mutex_unlock(&dev->device_lock);
770 if (wait_event_interruptible(cl->tx_wait,
771 cl->writing_state == MEI_WRITE_COMPLETE)) {
772 if (signal_pending(current))
773 rets = -EINTR;
774 else
775 rets = -ERESTARTSYS;
776 }
777 mutex_lock(&dev->device_lock);
778 }
779err:
780 return rets;
781}
782
783
784
785/**
681 * mei_cl_all_disconnect - disconnect forcefully all connected clients 786 * mei_cl_all_disconnect - disconnect forcefully all connected clients
682 * 787 *
683 * @dev - mei device 788 * @dev - mei device
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 214b2397ec3e..e890c8bf89d0 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -86,17 +86,16 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl);
86 */ 86 */
87bool mei_cl_is_other_connecting(struct mei_cl *cl); 87bool mei_cl_is_other_connecting(struct mei_cl *cl);
88int mei_cl_disconnect(struct mei_cl *cl); 88int mei_cl_disconnect(struct mei_cl *cl);
89
90int mei_cl_read_start(struct mei_cl *cl);
91
92int mei_cl_connect(struct mei_cl *cl, struct file *file); 89int mei_cl_connect(struct mei_cl *cl, struct file *file);
90int mei_cl_read_start(struct mei_cl *cl);
91int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking);
93 92
94void mei_host_client_init(struct work_struct *work); 93void mei_host_client_init(struct work_struct *work);
95 94
96 95
96
97void mei_cl_all_disconnect(struct mei_device *dev); 97void mei_cl_all_disconnect(struct mei_device *dev);
98void mei_cl_all_read_wakeup(struct mei_device *dev); 98void mei_cl_all_read_wakeup(struct mei_device *dev);
99void mei_cl_all_write_clear(struct mei_device *dev); 99void mei_cl_all_write_clear(struct mei_device *dev);
100 100
101
102#endif /* _MEI_CLIENT_H_ */ 101#endif /* _MEI_CLIENT_H_ */
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 329fb865cfd0..cb11b36512b5 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -342,11 +342,10 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
342{ 342{
343 struct mei_cl *cl = file->private_data; 343 struct mei_cl *cl = file->private_data;
344 struct mei_cl_cb *write_cb = NULL; 344 struct mei_cl_cb *write_cb = NULL;
345 struct mei_msg_hdr mei_hdr;
346 struct mei_device *dev; 345 struct mei_device *dev;
347 unsigned long timeout = 0; 346 unsigned long timeout = 0;
348 int rets; 347 int rets;
349 int i; 348 int id;
350 349
351 if (WARN_ON(!cl || !cl->dev)) 350 if (WARN_ON(!cl || !cl->dev))
352 return -ENODEV; 351 return -ENODEV;
@@ -357,24 +356,24 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
357 356
358 if (dev->dev_state != MEI_DEV_ENABLED) { 357 if (dev->dev_state != MEI_DEV_ENABLED) {
359 rets = -ENODEV; 358 rets = -ENODEV;
360 goto err; 359 goto out;
361 } 360 }
362 361
363 i = mei_me_cl_by_id(dev, cl->me_client_id); 362 id = mei_me_cl_by_id(dev, cl->me_client_id);
364 if (i < 0) { 363 if (id < 0) {
365 rets = -ENODEV; 364 rets = -ENODEV;
366 goto err; 365 goto out;
367 } 366 }
368 if (length > dev->me_clients[i].props.max_msg_length || length <= 0) { 367 if (length > dev->me_clients[id].props.max_msg_length || length <= 0) {
369 rets = -EMSGSIZE; 368 rets = -EMSGSIZE;
370 goto err; 369 goto out;
371 } 370 }
372 371
373 if (cl->state != MEI_FILE_CONNECTED) { 372 if (cl->state != MEI_FILE_CONNECTED) {
374 rets = -ENODEV;
375 dev_err(&dev->pdev->dev, "host client = %d, is not connected to ME client = %d", 373 dev_err(&dev->pdev->dev, "host client = %d, is not connected to ME client = %d",
376 cl->host_client_id, cl->me_client_id); 374 cl->host_client_id, cl->me_client_id);
377 goto err; 375 rets = -ENODEV;
376 goto out;
378 } 377 }
379 if (cl == &dev->iamthif_cl) { 378 if (cl == &dev->iamthif_cl) {
380 write_cb = mei_amthif_find_read_list_entry(dev, file); 379 write_cb = mei_amthif_find_read_list_entry(dev, file);
@@ -412,17 +411,15 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
412 if (!write_cb) { 411 if (!write_cb) {
413 dev_err(&dev->pdev->dev, "write cb allocation failed\n"); 412 dev_err(&dev->pdev->dev, "write cb allocation failed\n");
414 rets = -ENOMEM; 413 rets = -ENOMEM;
415 goto err; 414 goto out;
416 } 415 }
417 rets = mei_io_cb_alloc_req_buf(write_cb, length); 416 rets = mei_io_cb_alloc_req_buf(write_cb, length);
418 if (rets) 417 if (rets)
419 goto err; 418 goto out;
420
421 dev_dbg(&dev->pdev->dev, "cb request size = %zd\n", length);
422 419
423 rets = copy_from_user(write_cb->request_buffer.data, ubuf, length); 420 rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
424 if (rets) 421 if (rets)
425 goto err; 422 goto out;
426 423
427 cl->sm_state = 0; 424 cl->sm_state = 0;
428 if (length == 4 && 425 if (length == 4 &&
@@ -440,65 +437,17 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
440 if (rets) { 437 if (rets) {
441 dev_err(&dev->pdev->dev, 438 dev_err(&dev->pdev->dev,
442 "amthif write failed with status = %d\n", rets); 439 "amthif write failed with status = %d\n", rets);
443 goto err; 440 goto out;
444 } 441 }
445 mutex_unlock(&dev->device_lock); 442 mutex_unlock(&dev->device_lock);
446 return length; 443 return length;
447 } 444 }
448 445
449 write_cb->fop_type = MEI_FOP_WRITE; 446 rets = mei_cl_write(cl, write_cb, false);
450
451 dev_dbg(&dev->pdev->dev, "host client = %d, ME client = %d\n",
452 cl->host_client_id, cl->me_client_id);
453 rets = mei_cl_flow_ctrl_creds(cl);
454 if (rets < 0)
455 goto err;
456
457 if (rets == 0 || !dev->hbuf_is_ready) {
458 write_cb->buf_idx = 0;
459 mei_hdr.msg_complete = 0;
460 cl->writing_state = MEI_WRITING;
461 goto out;
462 }
463
464 dev->hbuf_is_ready = false;
465 if (length > mei_hbuf_max_len(dev)) {
466 mei_hdr.length = mei_hbuf_max_len(dev);
467 mei_hdr.msg_complete = 0;
468 } else {
469 mei_hdr.length = length;
470 mei_hdr.msg_complete = 1;
471 }
472 mei_hdr.host_addr = cl->host_client_id;
473 mei_hdr.me_addr = cl->me_client_id;
474 mei_hdr.reserved = 0;
475
476 dev_dbg(&dev->pdev->dev, "write " MEI_HDR_FMT "\n",
477 MEI_HDR_PRM(&mei_hdr));
478 if (mei_write_message(dev, &mei_hdr, write_cb->request_buffer.data)) {
479 rets = -ENODEV;
480 goto err;
481 }
482 cl->writing_state = MEI_WRITING;
483 write_cb->buf_idx = mei_hdr.length;
484
485out: 447out:
486 if (mei_hdr.msg_complete) {
487 if (mei_cl_flow_ctrl_reduce(cl)) {
488 rets = -ENODEV;
489 goto err;
490 }
491 list_add_tail(&write_cb->list, &dev->write_waiting_list.list);
492 } else {
493 list_add_tail(&write_cb->list, &dev->write_list.list);
494 }
495
496 mutex_unlock(&dev->device_lock);
497 return length;
498
499err:
500 mutex_unlock(&dev->device_lock); 448 mutex_unlock(&dev->device_lock);
501 mei_io_cb_free(write_cb); 449 if (rets < 0)
450 mei_io_cb_free(write_cb);
502 return rets; 451 return rets;
503} 452}
504 453
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 8806be420f6b..d786da6aa25b 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -153,7 +153,7 @@ enum mei_cb_file_ops {
153/* 153/*
154 * Intel MEI message data struct 154 * Intel MEI message data struct
155 */ 155 */
156struct mei_message_data { 156struct mei_msg_data {
157 u32 size; 157 u32 size;
158 unsigned char *data; 158 unsigned char *data;
159}; 159};
@@ -184,8 +184,8 @@ struct mei_cl_cb {
184 struct list_head list; 184 struct list_head list;
185 struct mei_cl *cl; 185 struct mei_cl *cl;
186 enum mei_cb_file_ops fop_type; 186 enum mei_cb_file_ops fop_type;
187 struct mei_message_data request_buffer; 187 struct mei_msg_data request_buffer;
188 struct mei_message_data response_buffer; 188 struct mei_msg_data response_buffer;
189 unsigned long buf_idx; 189 unsigned long buf_idx;
190 unsigned long read_time; 190 unsigned long read_time;
191 struct file *file_object; 191 struct file *file_object;