aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/client.c')
-rw-r--r--drivers/misc/mei/client.c103
1 files changed, 63 insertions, 40 deletions
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index e0684b4d9a08..fbd319c506e6 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -187,10 +187,14 @@ int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
187 */ 187 */
188int mei_cl_flush_queues(struct mei_cl *cl) 188int mei_cl_flush_queues(struct mei_cl *cl)
189{ 189{
190 struct mei_device *dev;
191
190 if (WARN_ON(!cl || !cl->dev)) 192 if (WARN_ON(!cl || !cl->dev))
191 return -EINVAL; 193 return -EINVAL;
192 194
193 dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n"); 195 dev = cl->dev;
196
197 cl_dbg(dev, cl, "remove list entry belonging to cl\n");
194 mei_io_list_flush(&cl->dev->read_list, cl); 198 mei_io_list_flush(&cl->dev->read_list, cl);
195 mei_io_list_flush(&cl->dev->write_list, cl); 199 mei_io_list_flush(&cl->dev->write_list, cl);
196 mei_io_list_flush(&cl->dev->write_waiting_list, cl); 200 mei_io_list_flush(&cl->dev->write_waiting_list, cl);
@@ -287,6 +291,12 @@ int mei_cl_link(struct mei_cl *cl, int id)
287 return -ENOENT; 291 return -ENOENT;
288 } 292 }
289 293
294 if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
295 dev_err(&dev->pdev->dev, "open_handle_count exceded %d",
296 MEI_MAX_OPEN_HANDLE_COUNT);
297 return -ENOENT;
298 }
299
290 dev->open_handle_count++; 300 dev->open_handle_count++;
291 301
292 cl->host_client_id = id; 302 cl->host_client_id = id;
@@ -296,7 +306,7 @@ int mei_cl_link(struct mei_cl *cl, int id)
296 306
297 cl->state = MEI_FILE_INITIALIZING; 307 cl->state = MEI_FILE_INITIALIZING;
298 308
299 dev_dbg(&dev->pdev->dev, "link cl host id = %d\n", cl->host_client_id); 309 cl_dbg(dev, cl, "link cl\n");
300 return 0; 310 return 0;
301} 311}
302 312
@@ -308,7 +318,6 @@ int mei_cl_link(struct mei_cl *cl, int id)
308int mei_cl_unlink(struct mei_cl *cl) 318int mei_cl_unlink(struct mei_cl *cl)
309{ 319{
310 struct mei_device *dev; 320 struct mei_device *dev;
311 struct mei_cl *pos, *next;
312 321
313 /* don't shout on error exit path */ 322 /* don't shout on error exit path */
314 if (!cl) 323 if (!cl)
@@ -320,14 +329,10 @@ int mei_cl_unlink(struct mei_cl *cl)
320 329
321 dev = cl->dev; 330 dev = cl->dev;
322 331
323 list_for_each_entry_safe(pos, next, &dev->file_list, link) { 332 cl_dbg(dev, cl, "unlink client");
324 if (cl->host_client_id == pos->host_client_id) { 333
325 dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n", 334 list_del_init(&cl->link);
326 pos->host_client_id, pos->me_client_id); 335
327 list_del_init(&pos->link);
328 break;
329 }
330 }
331 return 0; 336 return 0;
332} 337}
333 338
@@ -390,6 +395,8 @@ int mei_cl_disconnect(struct mei_cl *cl)
390 395
391 dev = cl->dev; 396 dev = cl->dev;
392 397
398 cl_dbg(dev, cl, "disconnecting");
399
393 if (cl->state != MEI_FILE_DISCONNECTING) 400 if (cl->state != MEI_FILE_DISCONNECTING)
394 return 0; 401 return 0;
395 402
@@ -402,13 +409,13 @@ int mei_cl_disconnect(struct mei_cl *cl)
402 dev->hbuf_is_ready = false; 409 dev->hbuf_is_ready = false;
403 if (mei_hbm_cl_disconnect_req(dev, cl)) { 410 if (mei_hbm_cl_disconnect_req(dev, cl)) {
404 rets = -ENODEV; 411 rets = -ENODEV;
405 dev_err(&dev->pdev->dev, "failed to disconnect.\n"); 412 cl_err(dev, cl, "failed to disconnect.\n");
406 goto free; 413 goto free;
407 } 414 }
408 mdelay(10); /* Wait for hardware disconnection ready */ 415 mdelay(10); /* Wait for hardware disconnection ready */
409 list_add_tail(&cb->list, &dev->ctrl_rd_list.list); 416 list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
410 } else { 417 } else {
411 dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n"); 418 cl_dbg(dev, cl, "add disconnect cb to control write list\n");
412 list_add_tail(&cb->list, &dev->ctrl_wr_list.list); 419 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
413 420
414 } 421 }
@@ -421,18 +428,17 @@ int mei_cl_disconnect(struct mei_cl *cl)
421 mutex_lock(&dev->device_lock); 428 mutex_lock(&dev->device_lock);
422 if (MEI_FILE_DISCONNECTED == cl->state) { 429 if (MEI_FILE_DISCONNECTED == cl->state) {
423 rets = 0; 430 rets = 0;
424 dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n"); 431 cl_dbg(dev, cl, "successfully disconnected from FW client.\n");
425 } else { 432 } else {
426 rets = -ENODEV; 433 rets = -ENODEV;
427 if (MEI_FILE_DISCONNECTED != cl->state) 434 if (MEI_FILE_DISCONNECTED != cl->state)
428 dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n"); 435 cl_err(dev, cl, "wrong status client disconnect.\n");
429 436
430 if (err) 437 if (err)
431 dev_dbg(&dev->pdev->dev, 438 cl_dbg(dev, cl, "wait failed disconnect err=%08x\n",
432 "wait failed disconnect err=%08x\n",
433 err); 439 err);
434 440
435 dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n"); 441 cl_err(dev, cl, "failed to disconnect from FW client.\n");
436 } 442 }
437 443
438 mei_io_list_flush(&dev->ctrl_rd_list, cl); 444 mei_io_list_flush(&dev->ctrl_rd_list, cl);
@@ -639,13 +645,12 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
639 return -ENODEV; 645 return -ENODEV;
640 646
641 if (cl->read_cb) { 647 if (cl->read_cb) {
642 dev_dbg(&dev->pdev->dev, "read is pending.\n"); 648 cl_dbg(dev, cl, "read is pending.\n");
643 return -EBUSY; 649 return -EBUSY;
644 } 650 }
645 i = mei_me_cl_by_id(dev, cl->me_client_id); 651 i = mei_me_cl_by_id(dev, cl->me_client_id);
646 if (i < 0) { 652 if (i < 0) {
647 dev_err(&dev->pdev->dev, "no such me client %d\n", 653 cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
648 cl->me_client_id);
649 return -ENODEV; 654 return -ENODEV;
650 } 655 }
651 656
@@ -664,6 +669,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
664 if (dev->hbuf_is_ready) { 669 if (dev->hbuf_is_ready) {
665 dev->hbuf_is_ready = false; 670 dev->hbuf_is_ready = false;
666 if (mei_hbm_cl_flow_control_req(dev, cl)) { 671 if (mei_hbm_cl_flow_control_req(dev, cl)) {
672 cl_err(dev, cl, "flow control send failed\n");
667 rets = -ENODEV; 673 rets = -ENODEV;
668 goto err; 674 goto err;
669 } 675 }
@@ -691,10 +697,32 @@ err:
691int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb, 697int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
692 s32 *slots, struct mei_cl_cb *cmpl_list) 698 s32 *slots, struct mei_cl_cb *cmpl_list)
693{ 699{
694 struct mei_device *dev = cl->dev; 700 struct mei_device *dev;
701 struct mei_msg_data *buf;
695 struct mei_msg_hdr mei_hdr; 702 struct mei_msg_hdr mei_hdr;
696 size_t len = cb->request_buffer.size - cb->buf_idx; 703 size_t len;
697 u32 msg_slots = mei_data2slots(len); 704 u32 msg_slots;
705 int rets;
706
707
708 if (WARN_ON(!cl || !cl->dev))
709 return -ENODEV;
710
711 dev = cl->dev;
712
713 buf = &cb->request_buffer;
714
715 rets = mei_cl_flow_ctrl_creds(cl);
716 if (rets < 0)
717 return rets;
718
719 if (rets == 0) {
720 cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
721 return 0;
722 }
723
724 len = buf->size - cb->buf_idx;
725 msg_slots = mei_data2slots(len);
698 726
699 mei_hdr.host_addr = cl->host_client_id; 727 mei_hdr.host_addr = cl->host_client_id;
700 mei_hdr.me_addr = cl->me_client_id; 728 mei_hdr.me_addr = cl->me_client_id;
@@ -714,16 +742,15 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
714 return 0; 742 return 0;
715 } 743 }
716 744
717 dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n", 745 cl_dbg(dev, cl, "buf: size = %d idx = %lu\n",
718 cb->request_buffer.size, cb->buf_idx); 746 cb->request_buffer.size, cb->buf_idx);
719 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
720 747
721 *slots -= msg_slots; 748 *slots -= msg_slots;
722 if (mei_write_message(dev, &mei_hdr, 749 rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
723 cb->request_buffer.data + cb->buf_idx)) { 750 if (rets) {
724 cl->status = -ENODEV; 751 cl->status = rets;
725 list_move_tail(&cb->list, &cmpl_list->list); 752 list_move_tail(&cb->list, &cmpl_list->list);
726 return -ENODEV; 753 return rets;
727 } 754 }
728 755
729 cl->status = 0; 756 cl->status = 0;
@@ -732,7 +759,7 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
732 759
733 if (mei_hdr.msg_complete) { 760 if (mei_hdr.msg_complete) {
734 if (mei_cl_flow_ctrl_reduce(cl)) 761 if (mei_cl_flow_ctrl_reduce(cl))
735 return -ENODEV; 762 return -EIO;
736 list_move_tail(&cb->list, &dev->write_waiting_list.list); 763 list_move_tail(&cb->list, &dev->write_waiting_list.list);
737 } 764 }
738 765
@@ -767,7 +794,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
767 794
768 buf = &cb->request_buffer; 795 buf = &cb->request_buffer;
769 796
770 dev_dbg(&dev->pdev->dev, "mei_cl_write %d\n", buf->size); 797 cl_dbg(dev, cl, "mei_cl_write %d\n", buf->size);
771 798
772 799
773 cb->fop_type = MEI_FOP_WRITE; 800 cb->fop_type = MEI_FOP_WRITE;
@@ -800,14 +827,10 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
800 mei_hdr.me_addr = cl->me_client_id; 827 mei_hdr.me_addr = cl->me_client_id;
801 mei_hdr.reserved = 0; 828 mei_hdr.reserved = 0;
802 829
803 dev_dbg(&dev->pdev->dev, "write " MEI_HDR_FMT "\n",
804 MEI_HDR_PRM(&mei_hdr));
805
806 830
807 if (mei_write_message(dev, &mei_hdr, buf->data)) { 831 rets = mei_write_message(dev, &mei_hdr, buf->data);
808 rets = -EIO; 832 if (rets)
809 goto err; 833 goto err;
810 }
811 834
812 cl->writing_state = MEI_WRITING; 835 cl->writing_state = MEI_WRITING;
813 cb->buf_idx = mei_hdr.length; 836 cb->buf_idx = mei_hdr.length;
@@ -898,11 +921,11 @@ void mei_cl_all_wakeup(struct mei_device *dev)
898 struct mei_cl *cl, *next; 921 struct mei_cl *cl, *next;
899 list_for_each_entry_safe(cl, next, &dev->file_list, link) { 922 list_for_each_entry_safe(cl, next, &dev->file_list, link) {
900 if (waitqueue_active(&cl->rx_wait)) { 923 if (waitqueue_active(&cl->rx_wait)) {
901 dev_dbg(&dev->pdev->dev, "Waking up reading client!\n"); 924 cl_dbg(dev, cl, "Waking up reading client!\n");
902 wake_up_interruptible(&cl->rx_wait); 925 wake_up_interruptible(&cl->rx_wait);
903 } 926 }
904 if (waitqueue_active(&cl->tx_wait)) { 927 if (waitqueue_active(&cl->tx_wait)) {
905 dev_dbg(&dev->pdev->dev, "Waking up writing client!\n"); 928 cl_dbg(dev, cl, "Waking up writing client!\n");
906 wake_up_interruptible(&cl->tx_wait); 929 wake_up_interruptible(&cl->tx_wait);
907 } 930 }
908 } 931 }