mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-25 15:02:13 +00:00
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>
This commit is contained in:
parent
5ed3dbf93c
commit
2550d719d3
@ -255,7 +255,12 @@ virtio_heci_add_client(struct virtio_heci *vheci,
|
|||||||
struct virtio_heci_client *client)
|
struct virtio_heci_client *client)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&vheci->list_mutex);
|
pthread_mutex_lock(&vheci->list_mutex);
|
||||||
LIST_INSERT_HEAD(&vheci->active_clients, client, list);
|
if (client->type == TYPE_HBM)
|
||||||
|
/* make sure hbm client at the head of the list */
|
||||||
|
LIST_INSERT_HEAD(&vheci->active_clients, client, list);
|
||||||
|
else
|
||||||
|
LIST_INSERT_AFTER(LIST_FIRST(&vheci->active_clients),
|
||||||
|
client, list);
|
||||||
pthread_mutex_unlock(&vheci->list_mutex);
|
pthread_mutex_unlock(&vheci->list_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -820,7 +825,6 @@ virtio_heci_hbm_handler(struct virtio_heci *vheci, void *data)
|
|||||||
DPRINTF(("vheci: HBM cmd[%d] is done!\n\r", hbm_cmd->cmd));
|
DPRINTF(("vheci: HBM cmd[%d] is done!\n\r", hbm_cmd->cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
virtio_heci_proc_tx(struct virtio_heci *vheci, struct virtio_vq_info *vq)
|
virtio_heci_proc_tx(struct virtio_heci *vheci, struct virtio_vq_info *vq)
|
||||||
{
|
{
|
||||||
@ -1013,118 +1017,104 @@ out:
|
|||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* caller need hold rx_mutex
|
/*
|
||||||
* return:
|
* Process the data received from native mei cdev and hbm emulation
|
||||||
* true - data processed
|
* handler, assemable related heci header then copy to rx virtqueue.
|
||||||
* fasle - need resched
|
|
||||||
*/
|
*/
|
||||||
static bool virtio_heci_proc_rx(struct virtio_heci *vheci,
|
static void
|
||||||
|
virtio_heci_proc_vclient_rx(struct virtio_heci_client *client,
|
||||||
struct virtio_vq_info *vq)
|
struct virtio_vq_info *vq)
|
||||||
{
|
{
|
||||||
struct iovec iov[VIRTIO_HECI_RXSEGS + 1];
|
struct iovec iov[VIRTIO_HECI_RXSEGS + 1];
|
||||||
struct heci_msg_hdr *heci_hdr;
|
struct heci_msg_hdr *heci_hdr;
|
||||||
int n;
|
uint16_t idx = 0;
|
||||||
uint16_t idx;
|
int n, len = 0;
|
||||||
struct virtio_heci_client *pclient, *client = NULL;
|
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
int len;
|
|
||||||
bool finished = false;
|
|
||||||
|
|
||||||
/* search all clients who has message received to fill the recv buf */
|
|
||||||
pthread_mutex_lock(&vheci->list_mutex);
|
|
||||||
LIST_FOREACH(pclient, &vheci->active_clients, list) {
|
|
||||||
if (pclient->recv_offset - pclient->recv_handled > 0) {
|
|
||||||
client = virtio_heci_client_get(pclient);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&vheci->list_mutex);
|
|
||||||
|
|
||||||
/* no client has data received, ignore RX request! */
|
|
||||||
if (!client) {
|
|
||||||
DPRINTF(("vheci: RX: none client has data!\n\r"));
|
|
||||||
vheci->rx_need_sched = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Obtain chain of descriptors.
|
|
||||||
* The first dword is heci_hdr, the rest are for payload.
|
|
||||||
*/
|
|
||||||
n = vq_getchain(vq, &idx, iov, VIRTIO_HECI_RXSEGS, NULL);
|
n = vq_getchain(vq, &idx, iov, VIRTIO_HECI_RXSEGS, NULL);
|
||||||
assert(n == VIRTIO_HECI_RXSEGS);
|
assert(n == VIRTIO_HECI_RXSEGS);
|
||||||
heci_hdr = (struct heci_msg_hdr *)iov[0].iov_base;
|
|
||||||
|
|
||||||
/* buffer length need remove HECI header */
|
|
||||||
len = (vheci->config->buf_depth - 1) * sizeof(struct heci_msg_hdr);
|
|
||||||
buf = (uint8_t *)iov[0].iov_base + sizeof(struct heci_msg_hdr);
|
|
||||||
|
|
||||||
if (client->type == TYPE_HBM) {
|
if (client->type == TYPE_HBM) {
|
||||||
/* HBM client has data to FE */
|
/* HBM client has data to FE */
|
||||||
len = client->recv_offset - client->recv_handled;
|
len = client->recv_offset - client->recv_handled;
|
||||||
memcpy(iov[0].iov_base,
|
memcpy(iov[0].iov_base,
|
||||||
client->recv_buf + client->recv_handled, len);
|
client->recv_buf + client->recv_handled, len);
|
||||||
DPRINTF(("vheci: RX: data DM:ME[%d]fd[%d]off[%d]"
|
client->recv_offset = client->recv_handled = 0;
|
||||||
" -> UOS:client_addr[%d] len[%d]\n\r",
|
DPRINTF(("vheci: RX: DM:ME[%d]fd[%d]off[%d]"
|
||||||
|
"-> UOS:client_addr[%d] len[%d]\n\r",
|
||||||
client->client_id, client->client_fd,
|
client->client_id, client->client_fd,
|
||||||
client->recv_handled,
|
client->recv_handled,
|
||||||
client->client_addr, len));
|
client->client_addr, len));
|
||||||
print_hex(iov[0].iov_base, len);
|
|
||||||
client->recv_offset = client->recv_handled = 0;
|
|
||||||
finished = true;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client->recv_creds == 0) {
|
/* NORMAL client buffer length need remove HECI header */
|
||||||
/*
|
len = (VIRTIO_HECI_FIFOSZ - 1) * sizeof(struct heci_msg_hdr);
|
||||||
* FE client is not ready to recv message
|
buf = (uint8_t *)iov[0].iov_base + sizeof(struct heci_msg_hdr);
|
||||||
* return 1 here to unmask rx_need_sched, to avoid spin in
|
heci_hdr = (struct heci_msg_hdr *)iov[0].iov_base;
|
||||||
* this checking loop, tag rx_need_sched when we receive creds
|
|
||||||
*/
|
if (client->recv_offset - client->recv_handled > len) {
|
||||||
DPRINTF(("vheci: RX: ME[%d]fd[%d] recv_creds is not ready\n\r",
|
|
||||||
client->client_id, client->client_fd));
|
|
||||||
virtio_heci_client_put(vheci, client);
|
|
||||||
vq_retchain(vq);
|
|
||||||
return true;
|
|
||||||
} else if (client->recv_offset - client->recv_handled > len) {
|
|
||||||
/* this client has data to guest, and
|
|
||||||
* need split the data into multi buffers
|
|
||||||
* FE only support one buffer now. Need expand later.
|
|
||||||
*/
|
|
||||||
populate_heci_hdr(client, heci_hdr, len, 0);
|
populate_heci_hdr(client, heci_hdr, len, 0);
|
||||||
memcpy(buf, client->recv_buf + client->recv_handled, len);
|
memcpy(buf, client->recv_buf + client->recv_handled, len);
|
||||||
|
client->recv_handled += len;
|
||||||
|
len += sizeof(struct heci_msg_hdr);
|
||||||
DPRINTF(("vheci: RX: data(partly) DM:ME[%d]fd[%d]off[%d]"
|
DPRINTF(("vheci: RX: data(partly) DM:ME[%d]fd[%d]off[%d]"
|
||||||
" -> UOS:client_addr[%d] len[%d]\n\r",
|
" -> UOS:client_addr[%d] len[%d]\n\r",
|
||||||
client->client_id, client->client_fd,
|
client->client_id, client->client_fd,
|
||||||
client->recv_handled,
|
client->recv_handled,
|
||||||
client->client_addr, len));
|
client->client_addr, len));
|
||||||
client->recv_handled += len;
|
|
||||||
finished = false;
|
|
||||||
len += sizeof(struct heci_msg_hdr);
|
|
||||||
} else {
|
} else {
|
||||||
/* this client has data to guest, can be in one recv buf */
|
/* this client has data to guest, can be in one recv buf */
|
||||||
len = client->recv_offset - client->recv_handled;
|
len = client->recv_offset - client->recv_handled;
|
||||||
populate_heci_hdr(client, heci_hdr, len, 1);
|
populate_heci_hdr(client, heci_hdr, len, 1);
|
||||||
memcpy(buf, client->recv_buf + client->recv_handled, len);
|
memcpy(buf, client->recv_buf + client->recv_handled, len);
|
||||||
client->recv_offset = client->recv_handled = 0;
|
client->recv_offset = client->recv_handled = 0;
|
||||||
finished = true;
|
|
||||||
client->recv_creds--;
|
client->recv_creds--;
|
||||||
len += sizeof(struct heci_msg_hdr);
|
len += sizeof(struct heci_msg_hdr);
|
||||||
DPRINTF(("vheci: RX: data(end) DM:ME[%d]fd[%d]off[%d]"
|
DPRINTF(("vheci: RX: data(end) DM:ME[%d]fd[%d]off[%d]"
|
||||||
"-> UOS:client_addr[%d] len[%d]\n\r",
|
" -> UOS:client_addr[%d] len[%d]\n\r",
|
||||||
client->client_id, client->client_fd,
|
client->client_id, client->client_fd,
|
||||||
client->recv_handled,
|
client->recv_handled,
|
||||||
client->client_addr, len));
|
client->client_addr, len));
|
||||||
print_hex((uint8_t *)iov[0].iov_base, len);
|
}
|
||||||
|
out:
|
||||||
|
vq_relchain(vq, idx, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* caller need hold rx_mutex
|
||||||
|
* return:
|
||||||
|
* true - data processed
|
||||||
|
* fasle - need resched
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
virtio_heci_proc_rx(struct virtio_heci *vheci,
|
||||||
|
struct virtio_vq_info *vq)
|
||||||
|
{
|
||||||
|
struct virtio_heci_client *pclient, *client = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Traverse the list find all available clients, ignore these normal
|
||||||
|
* type clients, which have data but it's receieve creds is Zero.
|
||||||
|
*/
|
||||||
|
pthread_mutex_lock(&vheci->list_mutex);
|
||||||
|
LIST_FOREACH(pclient, &vheci->active_clients, list) {
|
||||||
|
if ((pclient->recv_offset - pclient->recv_handled > 0) &&
|
||||||
|
(pclient->recv_creds > 0 || pclient->type == TYPE_HBM)) {
|
||||||
|
client = virtio_heci_client_get(pclient);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&vheci->list_mutex);
|
||||||
|
|
||||||
|
/* no client has data need to be processed */
|
||||||
|
if (!client) {
|
||||||
|
DPRINTF(("vheci: RX: no available client!\n\r"));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
virtio_heci_proc_vclient_rx(client, vq);
|
||||||
virtio_heci_client_put(vheci, client);
|
virtio_heci_client_put(vheci, client);
|
||||||
/* chain is processed, release it and set tlen */
|
return false;
|
||||||
vq_relchain(vq, idx, len);
|
|
||||||
DPRINTF(("vheci: RX: release IN-vq idx[%d]\r\n", idx));
|
|
||||||
|
|
||||||
return finished;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user