aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2013-01-08 16:07:15 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-01-08 19:40:45 -0500
commit9f81abdac3629629a246fdc9e2a7c01ffd52ce8a (patch)
tree4593dab5bdf44e200efe1fa72f3badb517cc8a12 /drivers/misc/mei
parent90e0b5f18569bdd03c5ddd1d8c99946f42af77b8 (diff)
mei: implement mei_cl_connect function
Implement mei_cl_connect that warps host client parts of the connection and leave the ioctl specifics in the mei_ioctl_connect_client function. Move mei_ioctl_connect_client to main.c where it belongs Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r--drivers/misc/mei/client.c219
-rw-r--r--drivers/misc/mei/main.c98
-rw-r--r--drivers/misc/mei/mei_dev.h5
3 files changed, 163 insertions, 159 deletions
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index e300637c89ed..cc3e76c60417 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -461,6 +461,71 @@ bool mei_cl_is_other_connecting(struct mei_cl *cl)
461} 461}
462 462
463/** 463/**
464 * mei_cl_connect - connect host clinet to the me one
465 *
466 * @cl: host client
467 *
468 * Locking: called under "dev->device_lock" lock
469 *
470 * returns 0 on success, <0 on failure.
471 */
472int mei_cl_connect(struct mei_cl *cl, struct file *file)
473{
474 struct mei_device *dev;
475 struct mei_cl_cb *cb;
476 long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
477 int rets;
478
479 if (WARN_ON(!cl || !cl->dev))
480 return -ENODEV;
481
482 dev = cl->dev;
483
484 cb = mei_io_cb_init(cl, file);
485 if (!cb) {
486 rets = -ENOMEM;
487 goto out;
488 }
489
490 cb->fop_type = MEI_FOP_IOCTL;
491
492 if (dev->mei_host_buffer_is_empty &&
493 !mei_cl_is_other_connecting(cl)) {
494 dev->mei_host_buffer_is_empty = false;
495
496 if (mei_hbm_cl_connect_req(dev, cl)) {
497 rets = -ENODEV;
498 goto out;
499 }
500 cl->timer_count = MEI_CONNECT_TIMEOUT;
501 list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
502 } else {
503 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
504 }
505
506 mutex_unlock(&dev->device_lock);
507 rets = wait_event_timeout(dev->wait_recvd_msg,
508 (cl->state == MEI_FILE_CONNECTED ||
509 cl->state == MEI_FILE_DISCONNECTED),
510 timeout * HZ);
511 mutex_lock(&dev->device_lock);
512
513 if (cl->state != MEI_FILE_CONNECTED) {
514 rets = -EFAULT;
515
516 mei_io_list_flush(&dev->ctrl_rd_list, cl);
517 mei_io_list_flush(&dev->ctrl_wr_list, cl);
518 goto out;
519 }
520
521 rets = cl->status;
522
523out:
524 mei_io_cb_free(cb);
525 return rets;
526}
527
528/**
464 * mei_cl_flow_ctrl_creds - checks flow_control credits for cl. 529 * mei_cl_flow_ctrl_creds - checks flow_control credits for cl.
465 * 530 *
466 * @dev: the device structure 531 * @dev: the device structure
@@ -542,160 +607,6 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
542 return -ENOENT; 607 return -ENOENT;
543} 608}
544 609
545
546
547/**
548 * mei_ioctl_connect_client - the connect to fw client IOCTL function
549 *
550 * @dev: the device structure
551 * @data: IOCTL connect data, input and output parameters
552 * @file: private data of the file object
553 *
554 * Locking: called under "dev->device_lock" lock
555 *
556 * returns 0 on success, <0 on failure.
557 */
558int mei_ioctl_connect_client(struct file *file,
559 struct mei_connect_client_data *data)
560{
561 struct mei_device *dev;
562 struct mei_cl_cb *cb;
563 struct mei_client *client;
564 struct mei_cl *cl;
565 long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
566 int i;
567 int err;
568 int rets;
569
570 cl = file->private_data;
571 if (WARN_ON(!cl || !cl->dev))
572 return -ENODEV;
573
574 dev = cl->dev;
575
576 dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
577
578 /* buffered ioctl cb */
579 cb = mei_io_cb_init(cl, file);
580 if (!cb) {
581 rets = -ENOMEM;
582 goto end;
583 }
584
585 cb->fop_type = MEI_FOP_IOCTL;
586
587 if (dev->dev_state != MEI_DEV_ENABLED) {
588 rets = -ENODEV;
589 goto end;
590 }
591 if (cl->state != MEI_FILE_INITIALIZING &&
592 cl->state != MEI_FILE_DISCONNECTED) {
593 rets = -EBUSY;
594 goto end;
595 }
596
597 /* find ME client we're trying to connect to */
598 i = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
599 if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
600 cl->me_client_id = dev->me_clients[i].client_id;
601 cl->state = MEI_FILE_CONNECTING;
602 }
603
604 dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
605 cl->me_client_id);
606 dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
607 dev->me_clients[i].props.protocol_version);
608 dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n",
609 dev->me_clients[i].props.max_msg_length);
610
611 /* if we're connecting to amthi client then we will use the
612 * existing connection
613 */
614 if (uuid_le_cmp(data->in_client_uuid, mei_amthi_guid) == 0) {
615 dev_dbg(&dev->pdev->dev, "FW Client is amthi\n");
616 if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
617 rets = -ENODEV;
618 goto end;
619 }
620 clear_bit(cl->host_client_id, dev->host_clients_map);
621 mei_cl_unlink(cl);
622
623 kfree(cl);
624 cl = NULL;
625 file->private_data = &dev->iamthif_cl;
626
627 client = &data->out_client_properties;
628 client->max_msg_length =
629 dev->me_clients[i].props.max_msg_length;
630 client->protocol_version =
631 dev->me_clients[i].props.protocol_version;
632 rets = dev->iamthif_cl.status;
633
634 goto end;
635 }
636
637 if (cl->state != MEI_FILE_CONNECTING) {
638 rets = -ENODEV;
639 goto end;
640 }
641
642
643 /* prepare the output buffer */
644 client = &data->out_client_properties;
645 client->max_msg_length = dev->me_clients[i].props.max_msg_length;
646 client->protocol_version = dev->me_clients[i].props.protocol_version;
647 dev_dbg(&dev->pdev->dev, "Can connect?\n");
648 if (dev->mei_host_buffer_is_empty &&
649 !mei_cl_is_other_connecting(cl)) {
650 dev_dbg(&dev->pdev->dev, "Sending Connect Message\n");
651 dev->mei_host_buffer_is_empty = false;
652 if (mei_hbm_cl_connect_req(dev, cl)) {
653 dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n");
654 rets = -ENODEV;
655 goto end;
656 } else {
657 dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
658 cl->timer_count = MEI_CONNECT_TIMEOUT;
659 list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
660 }
661
662
663 } else {
664 dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
665 dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
666 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
667 }
668 mutex_unlock(&dev->device_lock);
669 err = wait_event_timeout(dev->wait_recvd_msg,
670 (MEI_FILE_CONNECTED == cl->state ||
671 MEI_FILE_DISCONNECTED == cl->state), timeout);
672
673 mutex_lock(&dev->device_lock);
674 if (MEI_FILE_CONNECTED == cl->state) {
675 dev_dbg(&dev->pdev->dev, "successfully connected to FW client.\n");
676 rets = cl->status;
677 goto end;
678 } else {
679 dev_dbg(&dev->pdev->dev, "failed to connect to FW client.cl->state = %d.\n",
680 cl->state);
681 if (!err) {
682 dev_dbg(&dev->pdev->dev,
683 "wait_event_interruptible_timeout failed on client"
684 " connect message fw response message.\n");
685 }
686 rets = -EFAULT;
687
688 mei_io_list_flush(&dev->ctrl_rd_list, cl);
689 mei_io_list_flush(&dev->ctrl_wr_list, cl);
690 goto end;
691 }
692 rets = 0;
693end:
694 dev_dbg(&dev->pdev->dev, "free connect cb memory.");
695 mei_io_cb_free(cb);
696 return rets;
697}
698
699/** 610/**
700 * mei_cl_start_read - the start read client message function. 611 * mei_cl_start_read - the start read client message function.
701 * 612 *
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 95f05d97a115..8d3c134314c6 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -562,6 +562,103 @@ err:
562 return rets; 562 return rets;
563} 563}
564 564
565/**
566 * mei_ioctl_connect_client - the connect to fw client IOCTL function
567 *
568 * @dev: the device structure
569 * @data: IOCTL connect data, input and output parameters
570 * @file: private data of the file object
571 *
572 * Locking: called under "dev->device_lock" lock
573 *
574 * returns 0 on success, <0 on failure.
575 */
576static int mei_ioctl_connect_client(struct file *file,
577 struct mei_connect_client_data *data)
578{
579 struct mei_device *dev;
580 struct mei_client *client;
581 struct mei_cl *cl;
582 int i;
583 int rets;
584
585 cl = file->private_data;
586 if (WARN_ON(!cl || !cl->dev))
587 return -ENODEV;
588
589 dev = cl->dev;
590
591 if (dev->dev_state != MEI_DEV_ENABLED) {
592 rets = -ENODEV;
593 goto end;
594 }
595
596 if (cl->state != MEI_FILE_INITIALIZING &&
597 cl->state != MEI_FILE_DISCONNECTED) {
598 rets = -EBUSY;
599 goto end;
600 }
601
602 /* find ME client we're trying to connect to */
603 i = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
604 if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
605 cl->me_client_id = dev->me_clients[i].client_id;
606 cl->state = MEI_FILE_CONNECTING;
607 }
608
609 dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
610 cl->me_client_id);
611 dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
612 dev->me_clients[i].props.protocol_version);
613 dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n",
614 dev->me_clients[i].props.max_msg_length);
615
616 /* if we're connecting to amthi client then we will use the
617 * existing connection
618 */
619 if (uuid_le_cmp(data->in_client_uuid, mei_amthi_guid) == 0) {
620 dev_dbg(&dev->pdev->dev, "FW Client is amthi\n");
621 if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
622 rets = -ENODEV;
623 goto end;
624 }
625 clear_bit(cl->host_client_id, dev->host_clients_map);
626 mei_cl_unlink(cl);
627
628 kfree(cl);
629 cl = NULL;
630 file->private_data = &dev->iamthif_cl;
631
632 client = &data->out_client_properties;
633 client->max_msg_length =
634 dev->me_clients[i].props.max_msg_length;
635 client->protocol_version =
636 dev->me_clients[i].props.protocol_version;
637 rets = dev->iamthif_cl.status;
638
639 goto end;
640 }
641
642 if (cl->state != MEI_FILE_CONNECTING) {
643 rets = -ENODEV;
644 goto end;
645 }
646
647
648 /* prepare the output buffer */
649 client = &data->out_client_properties;
650 client->max_msg_length = dev->me_clients[i].props.max_msg_length;
651 client->protocol_version = dev->me_clients[i].props.protocol_version;
652 dev_dbg(&dev->pdev->dev, "Can connect?\n");
653
654
655 rets = mei_cl_connect(cl, file);
656
657end:
658 dev_dbg(&dev->pdev->dev, "free connect cb memory.");
659 return rets;
660}
661
565 662
566/** 663/**
567 * mei_ioctl - the IOCTL function 664 * mei_ioctl - the IOCTL function
@@ -610,6 +707,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
610 rets = -EFAULT; 707 rets = -EFAULT;
611 goto out; 708 goto out;
612 } 709 }
710
613 rets = mei_ioctl_connect_client(file, connect_data); 711 rets = mei_ioctl_connect_client(file, connect_data);
614 712
615 /* if all is ok, copying the data back to user. */ 713 /* if all is ok, copying the data back to user. */
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 5a1ac9a37e10..f3da1533c619 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -341,11 +341,6 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id);
341void mei_timer(struct work_struct *work); 341void mei_timer(struct work_struct *work);
342 342
343/* 343/*
344 * MEI input output function prototype
345 */
346int mei_ioctl_connect_client(struct file *file,
347 struct mei_connect_client_data *data);
348/*
349 * AMTHIF - AMT Host Interface Functions 344 * AMTHIF - AMT Host Interface Functions
350 */ 345 */
351void mei_amthif_reset_params(struct mei_device *dev); 346void mei_amthif_reset_params(struct mei_device *dev);