@@ -521,9 +521,232 @@ static void
521
521
virtio_heci_hbm_response (struct virtio_heci * vheci ,
522
522
struct heci_msg_hdr * hdr , void * data , int len )
523
523
{
524
- /* TODO: heci hbm response */
524
+ struct virtio_heci_client * client ;
525
+
526
+ client = virtio_heci_get_hbm_client (vheci );
527
+ if (!client ) {
528
+ DPRINTF (("vheci: HBM client has been released, ignore.\r\n" ));
529
+ return ;
530
+ }
531
+ pthread_mutex_lock (& vheci -> rx_mutex );
532
+ memcpy (client -> recv_buf + client -> recv_offset , hdr ,
533
+ sizeof (struct heci_msg_hdr ));
534
+ client -> recv_offset += sizeof (struct heci_msg_hdr );
535
+ memcpy (client -> recv_buf + client -> recv_offset , data , len );
536
+ client -> recv_offset += len ;
537
+ vheci -> rx_need_sched = true;
538
+
539
+ pthread_mutex_unlock (& vheci -> rx_mutex );
540
+ virtio_heci_client_put (vheci , client );
525
541
}
526
542
543
+ static void
544
+ virtio_heci_hbm_handler (struct virtio_heci * vheci , void * data )
545
+ {
546
+ struct heci_hbm_cmd * hbm_cmd = (struct heci_hbm_cmd * )data ;
547
+ struct heci_msg_hdr * phdr , hdr = {0 };
548
+ struct virtio_heci_client * client = NULL ;
549
+ struct mei_request_client_params params_req = {0 };
550
+ int ret = 0 , status = 0 ;
551
+
552
+ struct heci_hbm_host_ver_res ver_res = {{0 } };
553
+ struct heci_hbm_host_enum_req * enum_req ;
554
+ struct heci_hbm_host_enum_res enum_res = {{0 } };
555
+ struct heci_hbm_host_client_prop_req * client_prop_req ;
556
+ struct heci_hbm_host_client_prop_res client_prop_res = {{0 } };
557
+ struct heci_hbm_client_connect_req * connect_req ;
558
+ struct heci_hbm_client_connect_res connect_res = {{0 } };
559
+ struct heci_hbm_client_disconnect_res disconnect_res = {{0 } };
560
+ struct heci_hbm_flow_ctl flow_ctl_req = {{0 } };
561
+ struct heci_hbm_flow_ctl * pflow_ctl_req ;
562
+
563
+ DPRINTF (("vheci: HBM cmd[%d] is handling\n\r" , hbm_cmd -> cmd ));
564
+ phdr = & hdr ;
565
+ switch (hbm_cmd -> cmd ) {
566
+ case HECI_HBM_HOST_VERSION :
567
+ ver_res = * (struct heci_hbm_host_ver_res * )data ;
568
+ ver_res .hbm_cmd .is_response = 1 ;
569
+ /* always support host request version */
570
+ ver_res .host_ver_support = 1 ;
571
+ populate_heci_hdr (vheci -> hbm_client , phdr ,
572
+ sizeof (struct heci_hbm_host_ver_res ), 1 );
573
+ DPRINTF (("vheci: HBM cmd[%d] response: hdr[%08x]\n\r" ,
574
+ hbm_cmd -> cmd , * (unsigned int * )phdr ));
575
+ print_hex ((unsigned char * )& ver_res , sizeof (ver_res ));
576
+ virtio_heci_hbm_response (vheci , phdr ,
577
+ & ver_res , sizeof (ver_res ));
578
+ break ;
579
+ case HECI_HBM_HOST_STOP :
580
+ /* TODO:
581
+ * disconnect all clients
582
+ */
583
+ DPRINTF (("vheci: %s HBM cmd[%d] not support for now\n\r" ,
584
+ __func__ , hbm_cmd -> cmd ));
585
+ break ;
586
+ case HECI_HBM_ME_STOP :
587
+ /* TODO:
588
+ * reset all device
589
+ */
590
+ DPRINTF (("vheci: %s HBM cmd[%d] not support for now\n\r" ,
591
+ __func__ , hbm_cmd -> cmd ));
592
+ break ;
593
+ case HECI_HBM_HOST_ENUM :
594
+ enum_req = (struct heci_hbm_host_enum_req * )data ;
595
+ enum_res .hbm_cmd = enum_req -> hbm_cmd ;
596
+ enum_res .hbm_cmd .is_response = 1 ;
597
+ /* copy valid_addresses for hbm enum request */
598
+ memcpy (enum_res .valid_addresses , & vheci -> me_clients_map ,
599
+ sizeof (enum_res .valid_addresses ));
600
+ populate_heci_hdr (vheci -> hbm_client , phdr ,
601
+ sizeof (struct heci_hbm_host_enum_res ), 1 );
602
+ DPRINTF (("vheci: HBM cmd[%d] response: hdr[%08x]\n\r" ,
603
+ hbm_cmd -> cmd , * (unsigned int * )phdr ));
604
+ print_hex ((unsigned char * )& enum_res , sizeof (enum_res ));
605
+ virtio_heci_hbm_response (vheci , phdr ,
606
+ & enum_res , sizeof (enum_res ));
607
+ break ;
608
+ case HECI_HBM_HOST_CLIENT_PROP :
609
+ client_prop_req = (struct heci_hbm_host_client_prop_req * )data ;
610
+ client_prop_res .hbm_cmd = client_prop_req -> hbm_cmd ;
611
+ client_prop_res .hbm_cmd .is_response = 1 ;
612
+
613
+ client_prop_res .status = HECI_HBM_SUCCESS ;
614
+ /* get the client's props */
615
+ client_prop_res .address = params_req .client_id =
616
+ client_prop_req -> address ;
617
+ ret = ioctl (vheci -> hbm_client -> client_fd ,
618
+ IOCTL_MEI_REQUEST_CLIENT_PROP , & params_req );
619
+ if (ret < 0 ) {
620
+ /* not client found */
621
+ client_prop_res .status = HECI_HBM_CLIENT_NOT_FOUND ;
622
+ }
623
+ memcpy (& client_prop_res .props , params_req .data ,
624
+ sizeof (struct heci_client_properties ));
625
+ populate_heci_hdr (vheci -> hbm_client , phdr ,
626
+ sizeof (struct heci_hbm_host_client_prop_res ), 1 );
627
+ DPRINTF (("vheci: HBM cmd[%d] response: hdr[%08x]\n\r" ,
628
+ hbm_cmd -> cmd , * (unsigned int * )phdr ));
629
+ print_hex ((unsigned char * )& client_prop_res ,
630
+ sizeof (client_prop_res ));
631
+ virtio_heci_hbm_response (vheci , phdr ,
632
+ & client_prop_res , sizeof (client_prop_res ));
633
+ break ;
634
+ case HECI_HBM_CLIENT_CONNECT :
635
+ /*
636
+ * need handle some driver probed clients.
637
+ * There are some single connection clients with kernel
638
+ * driver probed, like DAL's VM clients, we need emulate
639
+ * the response to guest and setup the link between
640
+ * virtio_heci_client and front-end client
641
+ */
642
+ connect_req = (struct heci_hbm_client_connect_req * )data ;
643
+ connect_res =
644
+ * (struct heci_hbm_client_connect_res * )connect_req ;
645
+ connect_res .hbm_cmd .is_response = 1 ;
646
+ client = virtio_heci_find_client (vheci , connect_req -> host_addr );
647
+ if (!client ) {
648
+ /* no client mapping in mediator, need create */
649
+ client = virtio_heci_create_client (vheci ,
650
+ connect_req -> me_addr ,
651
+ connect_req -> host_addr , & status );
652
+ if (!client ) {
653
+ /* create client failed
654
+ * TODO: need change the status according to
655
+ * the status of virtio_heci_create_client.
656
+ */
657
+ connect_res .status = status ;
658
+ } else
659
+ virtio_heci_client_get (client );
660
+ } else {
661
+ /* already exist, return @HECI_HBM_ALREADY_EXISTS */
662
+ connect_res .status = HECI_HBM_ALREADY_EXISTS ;
663
+ }
664
+ populate_heci_hdr (vheci -> hbm_client , phdr ,
665
+ sizeof (struct heci_hbm_client_connect_res ), 1 );
666
+ DPRINTF (("vheci: HBM cmd[%d] response: hdr[%08x]\n\r" ,
667
+ hbm_cmd -> cmd , * (unsigned int * )phdr ));
668
+ print_hex ((unsigned char * )& connect_res , sizeof (connect_res ));
669
+ virtio_heci_hbm_response (vheci , phdr ,
670
+ & connect_res , sizeof (connect_res ));
671
+
672
+ /* create client failed, not need to send flow control */
673
+ if (!client ) {
674
+ DPRINTF (("vheci: create client failed.\r\n" ));
675
+ break ;
676
+ }
677
+
678
+ /* Give guest a flow control credit to let it send msssage */
679
+ flow_ctl_req .hbm_cmd .cmd = HECI_HBM_FLOW_CONTROL ;
680
+ flow_ctl_req .me_addr = client -> client_id ;
681
+ /*
682
+ * single recv buffer client,
683
+ */
684
+ if (client -> props .single_recv_buf )
685
+ flow_ctl_req .host_addr = 0 ;
686
+ else
687
+ flow_ctl_req .host_addr = client -> client_addr ;
688
+
689
+ virtio_heci_client_put (vheci , client );
690
+ populate_heci_hdr (vheci -> hbm_client , phdr ,
691
+ sizeof (struct heci_hbm_flow_ctl ), 1 );
692
+ DPRINTF (("vheci: HBM flow control: hdr[%08x]\n\r" ,
693
+ * (unsigned int * )phdr ));
694
+ print_hex ((unsigned char * )& flow_ctl_req , sizeof (flow_ctl_req ));
695
+ virtio_heci_hbm_response (vheci , phdr ,
696
+ & flow_ctl_req , sizeof (flow_ctl_req ));
697
+ break ;
698
+ case HECI_HBM_CLIENT_DISCONNECT :
699
+ disconnect_res = * (struct heci_hbm_client_disconnect_res * )data ;
700
+ if (!hbm_cmd -> is_response ) {
701
+ disconnect_res .hbm_cmd .is_response = 1 ;
702
+ disconnect_res .status = 0 ;
703
+ populate_heci_hdr (vheci -> hbm_client , phdr ,
704
+ sizeof (struct heci_hbm_client_disconnect_res ),
705
+ 1 );
706
+ virtio_heci_hbm_response (vheci , phdr ,
707
+ & disconnect_res , sizeof (disconnect_res ));
708
+ }
709
+ client = virtio_heci_find_client (vheci ,
710
+ disconnect_res .host_addr );
711
+ if (client ) {
712
+ virtio_heci_client_put (vheci , client );
713
+ /* put once more as find_client will get ref */
714
+ virtio_heci_client_put (vheci , client );
715
+ } else
716
+ DPRINTF (("vheci: client has been disconnected!!\r\n" ));
717
+ break ;
718
+ case HECI_HBM_FLOW_CONTROL :
719
+ /*
720
+ * FE client is ready, we can send message
721
+ */
722
+ pflow_ctl_req = (struct heci_hbm_flow_ctl * )data ;
723
+ client = virtio_heci_find_client (vheci ,
724
+ pflow_ctl_req -> host_addr );
725
+ if (client ) {
726
+ client -> recv_creds ++ ;
727
+ virtio_heci_client_put (vheci , client );
728
+ pthread_mutex_lock (& vheci -> rx_mutex );
729
+ vheci -> rx_need_sched = true;
730
+ pthread_mutex_unlock (& vheci -> rx_mutex );
731
+ } else
732
+ DPRINTF (("vheci: client has been released.\r\n" ));
733
+ break ;
734
+ case HECI_HBM_CLIENT_CONNECTION_RESET :
735
+ /* TODO:
736
+ * disconnect all clients
737
+ */
738
+ DPRINTF (("vheci: %s HBM cmd[%d] not support for now\n\r" ,
739
+ __func__ , hbm_cmd -> cmd ));
740
+ break ;
741
+ default :
742
+ DPRINTF (("vheci: %s HBM cmd[%d] not support for now\n\r" ,
743
+ __func__ , hbm_cmd -> cmd ));
744
+ break ;
745
+ }
746
+ DPRINTF (("vheci: HBM cmd[%d] is done!\n\r" , hbm_cmd -> cmd ));
747
+ }
748
+
749
+
527
750
static void
528
751
virtio_heci_proc_tx (struct virtio_heci * vheci , struct virtio_vq_info * vq )
529
752
{
@@ -550,8 +773,17 @@ virtio_heci_proc_tx(struct virtio_heci *vheci, struct virtio_vq_info *vq)
550
773
551
774
if (hdr_is_hbm (heci_hdr )) {
552
775
/*
553
- * TODO: hbm client handler
776
+ * hbm client handler
777
+ * all hbm will be complete in one msg package,
778
+ * so handle here directly
554
779
*/
780
+ hbm_client = virtio_heci_get_hbm_client (vheci );
781
+ if (!hbm_client ) {
782
+ DPRINTF (("vheci: TX: HBM client get fail!!\r\n" ));
783
+ goto failed ;
784
+ }
785
+ virtio_heci_hbm_handler (vheci , (void * )iov [1 ].iov_base );
786
+ virtio_heci_client_put (vheci , hbm_client );
555
787
} else if (hdr_is_fixed (heci_hdr )) {
556
788
/*
557
789
* TODO: fixed address client handler
0 commit comments