Skip to content

Commit 2550d71

Browse files
liudlongjren1
authored andcommitted
Subject: DM: virtio-heci: process all available client each time
Right now, the virtio_heci_proc_rx only process the first available client at a time, then clear rx_need_sched flag to make rx_thread sleep. It cause the remain data available clients lost the current change to be processed. This patch resolves this issue, to process all data available clients in a round prior to push rx_thread enter sleep. Signed-off-by: Long Liu <long.liu@intel.com> Reviewed-by: Shuo Liu <shuo.a.liu@intel.com> Reviewed-by: Yu Wang <yu1.wang@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 5ed3dbf commit 2550d71

File tree

1 file changed

+61
-71
lines changed

1 file changed

+61
-71
lines changed

devicemodel/hw/pci/virtio/virtio_heci.c

Lines changed: 61 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,12 @@ virtio_heci_add_client(struct virtio_heci *vheci,
255255
struct virtio_heci_client *client)
256256
{
257257
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);
259264
pthread_mutex_unlock(&vheci->list_mutex);
260265
}
261266

@@ -820,7 +825,6 @@ virtio_heci_hbm_handler(struct virtio_heci *vheci, void *data)
820825
DPRINTF(("vheci: HBM cmd[%d] is done!\n\r", hbm_cmd->cmd));
821826
}
822827

823-
824828
static void
825829
virtio_heci_proc_tx(struct virtio_heci *vheci, struct virtio_vq_info *vq)
826830
{
@@ -1013,118 +1017,104 @@ static void *virtio_heci_tx_thread(void *param)
10131017
pthread_exit(NULL);
10141018
}
10151019

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.
10201023
*/
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,
10221026
struct virtio_vq_info *vq)
10231027
{
10241028
struct iovec iov[VIRTIO_HECI_RXSEGS + 1];
10251029
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;
10291032
uint8_t *buf;
1030-
int len;
1031-
bool finished = false;
10321033

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-
*/
10541034
n = vq_getchain(vq, &idx, iov, VIRTIO_HECI_RXSEGS, NULL);
10551035
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);
10611036

10621037
if (client->type == TYPE_HBM) {
10631038
/* HBM client has data to FE */
10641039
len = client->recv_offset - client->recv_handled;
10651040
memcpy(iov[0].iov_base,
10661041
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",
10691045
client->client_id, client->client_fd,
10701046
client->recv_handled,
10711047
client->client_addr, len));
1072-
print_hex(iov[0].iov_base, len);
1073-
client->recv_offset = client->recv_handled = 0;
1074-
finished = true;
10751048
goto out;
10761049
}
10771050

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) {
10941057
populate_heci_hdr(client, heci_hdr, len, 0);
10951058
memcpy(buf, client->recv_buf + client->recv_handled, len);
1059+
client->recv_handled += len;
1060+
len += sizeof(struct heci_msg_hdr);
10961061
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",
10981063
client->client_id, client->client_fd,
10991064
client->recv_handled,
11001065
client->client_addr, len));
1101-
client->recv_handled += len;
1102-
finished = false;
1103-
len += sizeof(struct heci_msg_hdr);
11041066
} else {
11051067
/* this client has data to guest, can be in one recv buf */
11061068
len = client->recv_offset - client->recv_handled;
11071069
populate_heci_hdr(client, heci_hdr, len, 1);
11081070
memcpy(buf, client->recv_buf + client->recv_handled, len);
11091071
client->recv_offset = client->recv_handled = 0;
1110-
finished = true;
11111072
client->recv_creds--;
11121073
len += sizeof(struct heci_msg_hdr);
11131074
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",
11151076
client->client_id, client->client_fd,
11161077
client->recv_handled,
11171078
client->client_addr, len));
1118-
print_hex((uint8_t *)iov[0].iov_base, len);
11191079
}
1120-
11211080
out:
1122-
virtio_heci_client_put(vheci, client);
1123-
/* chain is processed, release it and set tlen */
11241081
vq_relchain(vq, idx, len);
1125-
DPRINTF(("vheci: RX: release IN-vq idx[%d]\r\n", idx));
1082+
}
11261083

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;
11281118
}
11291119

11301120
/*

0 commit comments

Comments
 (0)