@@ -255,7 +255,12 @@ virtio_heci_add_client(struct virtio_heci *vheci,
255
255
struct virtio_heci_client * client )
256
256
{
257
257
pthread_mutex_lock (& vheci -> list_mutex );
258
- LIST_INSERT_HEAD (& vheci -> active_clients , client , list );
258
+ if (client -> type == TYPE_HBM )
259
+ /* make sure hbm client at the head of the list */
260
+ LIST_INSERT_HEAD (& vheci -> active_clients , client , list );
261
+ else
262
+ LIST_INSERT_AFTER (LIST_FIRST (& vheci -> active_clients ),
263
+ client , list );
259
264
pthread_mutex_unlock (& vheci -> list_mutex );
260
265
}
261
266
@@ -820,7 +825,6 @@ virtio_heci_hbm_handler(struct virtio_heci *vheci, void *data)
820
825
DPRINTF (("vheci: HBM cmd[%d] is done!\n\r" , hbm_cmd -> cmd ));
821
826
}
822
827
823
-
824
828
static void
825
829
virtio_heci_proc_tx (struct virtio_heci * vheci , struct virtio_vq_info * vq )
826
830
{
@@ -1013,118 +1017,104 @@ static void *virtio_heci_tx_thread(void *param)
1013
1017
pthread_exit (NULL );
1014
1018
}
1015
1019
1016
- /* caller need hold rx_mutex
1017
- * return:
1018
- * true - data processed
1019
- * fasle - need resched
1020
+ /*
1021
+ * Process the data received from native mei cdev and hbm emulation
1022
+ * handler, assemable related heci header then copy to rx virtqueue.
1020
1023
*/
1021
- static bool virtio_heci_proc_rx (struct virtio_heci * vheci ,
1024
+ static void
1025
+ virtio_heci_proc_vclient_rx (struct virtio_heci_client * client ,
1022
1026
struct virtio_vq_info * vq )
1023
1027
{
1024
1028
struct iovec iov [VIRTIO_HECI_RXSEGS + 1 ];
1025
1029
struct heci_msg_hdr * heci_hdr ;
1026
- int n ;
1027
- uint16_t idx ;
1028
- struct virtio_heci_client * pclient , * client = NULL ;
1030
+ uint16_t idx = 0 ;
1031
+ int n , len = 0 ;
1029
1032
uint8_t * buf ;
1030
- int len ;
1031
- bool finished = false;
1032
1033
1033
- /* search all clients who has message received to fill the recv buf */
1034
- pthread_mutex_lock (& vheci -> list_mutex );
1035
- LIST_FOREACH (pclient , & vheci -> active_clients , list ) {
1036
- if (pclient -> recv_offset - pclient -> recv_handled > 0 ) {
1037
- client = virtio_heci_client_get (pclient );
1038
- break ;
1039
- }
1040
- }
1041
- pthread_mutex_unlock (& vheci -> list_mutex );
1042
-
1043
- /* no client has data received, ignore RX request! */
1044
- if (!client ) {
1045
- DPRINTF (("vheci: RX: none client has data!\n\r" ));
1046
- vheci -> rx_need_sched = false;
1047
- return false;
1048
- }
1049
-
1050
- /*
1051
- * Obtain chain of descriptors.
1052
- * The first dword is heci_hdr, the rest are for payload.
1053
- */
1054
1034
n = vq_getchain (vq , & idx , iov , VIRTIO_HECI_RXSEGS , NULL );
1055
1035
assert (n == VIRTIO_HECI_RXSEGS );
1056
- heci_hdr = (struct heci_msg_hdr * )iov [0 ].iov_base ;
1057
-
1058
- /* buffer length need remove HECI header */
1059
- len = (vheci -> config -> buf_depth - 1 ) * sizeof (struct heci_msg_hdr );
1060
- buf = (uint8_t * )iov [0 ].iov_base + sizeof (struct heci_msg_hdr );
1061
1036
1062
1037
if (client -> type == TYPE_HBM ) {
1063
1038
/* HBM client has data to FE */
1064
1039
len = client -> recv_offset - client -> recv_handled ;
1065
1040
memcpy (iov [0 ].iov_base ,
1066
1041
client -> recv_buf + client -> recv_handled , len );
1067
- DPRINTF (("vheci: RX: data DM:ME[%d]fd[%d]off[%d]"
1068
- " -> UOS:client_addr[%d] len[%d]\n\r" ,
1042
+ client -> recv_offset = client -> recv_handled = 0 ;
1043
+ DPRINTF (("vheci: RX: DM:ME[%d]fd[%d]off[%d]"
1044
+ "-> UOS:client_addr[%d] len[%d]\n\r" ,
1069
1045
client -> client_id , client -> client_fd ,
1070
1046
client -> recv_handled ,
1071
1047
client -> client_addr , len ));
1072
- print_hex (iov [0 ].iov_base , len );
1073
- client -> recv_offset = client -> recv_handled = 0 ;
1074
- finished = true;
1075
1048
goto out ;
1076
1049
}
1077
1050
1078
- if (client -> recv_creds == 0 ) {
1079
- /*
1080
- * FE client is not ready to recv message
1081
- * return 1 here to unmask rx_need_sched, to avoid spin in
1082
- * this checking loop, tag rx_need_sched when we receive creds
1083
- */
1084
- DPRINTF (("vheci: RX: ME[%d]fd[%d] recv_creds is not ready\n\r" ,
1085
- client -> client_id , client -> client_fd ));
1086
- virtio_heci_client_put (vheci , client );
1087
- vq_retchain (vq );
1088
- return true;
1089
- } else if (client -> recv_offset - client -> recv_handled > len ) {
1090
- /* this client has data to guest, and
1091
- * need split the data into multi buffers
1092
- * FE only support one buffer now. Need expand later.
1093
- */
1051
+ /* NORMAL client buffer length need remove HECI header */
1052
+ len = (VIRTIO_HECI_FIFOSZ - 1 ) * sizeof (struct heci_msg_hdr );
1053
+ buf = (uint8_t * )iov [0 ].iov_base + sizeof (struct heci_msg_hdr );
1054
+ heci_hdr = (struct heci_msg_hdr * )iov [0 ].iov_base ;
1055
+
1056
+ if (client -> recv_offset - client -> recv_handled > len ) {
1094
1057
populate_heci_hdr (client , heci_hdr , len , 0 );
1095
1058
memcpy (buf , client -> recv_buf + client -> recv_handled , len );
1059
+ client -> recv_handled += len ;
1060
+ len += sizeof (struct heci_msg_hdr );
1096
1061
DPRINTF (("vheci: RX: data(partly) DM:ME[%d]fd[%d]off[%d]"
1097
- " -> UOS:client_addr[%d] len[%d]\n\r" ,
1062
+ " -> UOS:client_addr[%d] len[%d]\n\r" ,
1098
1063
client -> client_id , client -> client_fd ,
1099
1064
client -> recv_handled ,
1100
1065
client -> client_addr , len ));
1101
- client -> recv_handled += len ;
1102
- finished = false;
1103
- len += sizeof (struct heci_msg_hdr );
1104
1066
} else {
1105
1067
/* this client has data to guest, can be in one recv buf */
1106
1068
len = client -> recv_offset - client -> recv_handled ;
1107
1069
populate_heci_hdr (client , heci_hdr , len , 1 );
1108
1070
memcpy (buf , client -> recv_buf + client -> recv_handled , len );
1109
1071
client -> recv_offset = client -> recv_handled = 0 ;
1110
- finished = true;
1111
1072
client -> recv_creds -- ;
1112
1073
len += sizeof (struct heci_msg_hdr );
1113
1074
DPRINTF (("vheci: RX: data(end) DM:ME[%d]fd[%d]off[%d]"
1114
- " -> UOS:client_addr[%d] len[%d]\n\r" ,
1075
+ " -> UOS:client_addr[%d] len[%d]\n\r" ,
1115
1076
client -> client_id , client -> client_fd ,
1116
1077
client -> recv_handled ,
1117
1078
client -> client_addr , len ));
1118
- print_hex ((uint8_t * )iov [0 ].iov_base , len );
1119
1079
}
1120
-
1121
1080
out :
1122
- virtio_heci_client_put (vheci , client );
1123
- /* chain is processed, release it and set tlen */
1124
1081
vq_relchain (vq , idx , len );
1125
- DPRINTF (( "vheci: RX: release IN-vq idx[%d]\r\n" , idx ));
1082
+ }
1126
1083
1127
- return finished ;
1084
+ /* caller need hold rx_mutex
1085
+ * return:
1086
+ * true - data processed
1087
+ * fasle - need resched
1088
+ */
1089
+ static bool
1090
+ virtio_heci_proc_rx (struct virtio_heci * vheci ,
1091
+ struct virtio_vq_info * vq )
1092
+ {
1093
+ struct virtio_heci_client * pclient , * client = NULL ;
1094
+
1095
+ /*
1096
+ * Traverse the list find all available clients, ignore these normal
1097
+ * type clients, which have data but it's receieve creds is Zero.
1098
+ */
1099
+ pthread_mutex_lock (& vheci -> list_mutex );
1100
+ LIST_FOREACH (pclient , & vheci -> active_clients , list ) {
1101
+ if ((pclient -> recv_offset - pclient -> recv_handled > 0 ) &&
1102
+ (pclient -> recv_creds > 0 || pclient -> type == TYPE_HBM )) {
1103
+ client = virtio_heci_client_get (pclient );
1104
+ break ;
1105
+ }
1106
+ }
1107
+ pthread_mutex_unlock (& vheci -> list_mutex );
1108
+
1109
+ /* no client has data need to be processed */
1110
+ if (!client ) {
1111
+ DPRINTF (("vheci: RX: no available client!\n\r" ));
1112
+ return true;
1113
+ }
1114
+
1115
+ virtio_heci_proc_vclient_rx (client , vq );
1116
+ virtio_heci_client_put (vheci , client );
1117
+ return false;
1128
1118
}
1129
1119
1130
1120
/*
0 commit comments