| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762 |
- /*-
- * Copyright (c) 2011, Bryan Venteicher <bryanv@FreeBSD.org>
- * Copyright (c) 2016 Freescale Semiconductor, Inc.
- * Copyright 2016-2019 NXP
- * All rights reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice unmodified, this list of conditions, and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "rpmsg_env.h"
- #include "virtqueue.h"
- /* Prototype for internal functions. */
- static void vq_ring_update_avail(struct virtqueue *vq, uint16_t desc_idx);
- static void vq_ring_update_used(struct virtqueue *vq, uint16_t head_idx, uint32_t len);
- static uint16_t vq_ring_add_buffer(
- struct virtqueue *vq, struct vring_desc *desc, uint16_t head_idx, void *buffer, uint32_t length);
- static int32_t vq_ring_enable_interrupt(struct virtqueue *vq, uint16_t ndesc);
- static int32_t vq_ring_must_notify_host(struct virtqueue *vq);
- static void vq_ring_notify_host(struct virtqueue *vq);
- static uint16_t virtqueue_nused(struct virtqueue *vq);
- #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
- /*!
- * virtqueue_create_static - Creates new VirtIO queue - static version
- *
- * @param id - VirtIO queue ID , must be unique
- * @param name - Name of VirtIO queue
- * @param ring - Pointer to vring_alloc_info control block
- * @param callback - Pointer to callback function, invoked
- * when message is available on VirtIO queue
- * @param notify - Pointer to notify function, used to notify
- * other side that there is job available for it
- * @param v_queue - Created VirtIO queue.
- * @param vq_ctxt - Statically allocated virtqueue context
- *
- * @return - Function status
- */
- int32_t virtqueue_create_static(uint16_t id,
- const char *name,
- struct vring_alloc_info *ring,
- void (*callback_fc)(struct virtqueue *vq),
- void (*notify_fc)(struct virtqueue *vq),
- struct virtqueue **v_queue,
- struct vq_static_context *vq_ctxt)
- {
- struct virtqueue *vq = VQ_NULL;
- volatile int32_t status = VQUEUE_SUCCESS;
- uint32_t vq_size = 0U;
- VQ_PARAM_CHK(vq_ctxt == VQ_NULL, status, ERROR_VQUEUE_INVLD_PARAM);
- VQ_PARAM_CHK(ring == VQ_NULL, status, ERROR_VQUEUE_INVLD_PARAM);
- VQ_PARAM_CHK(ring->num_descs == 0U, status, ERROR_VQUEUE_INVLD_PARAM);
- VQ_PARAM_CHK(ring->num_descs & (ring->num_descs - 1U), status, ERROR_VRING_ALIGN);
- if (status == VQUEUE_SUCCESS)
- {
- vq_size = sizeof(struct virtqueue);
- vq = &vq_ctxt->vq;
- env_memset(vq, 0x00, vq_size);
- env_strncpy(vq->vq_name, name, VIRTQUEUE_MAX_NAME_SZ);
- vq->vq_queue_index = id;
- vq->vq_alignment = (int32_t)(ring->align);
- vq->vq_nentries = ring->num_descs;
- vq->callback_fc = callback_fc;
- vq->notify_fc = notify_fc;
- // indirect addition is not supported
- vq->vq_ring_size = vring_size(ring->num_descs, ring->align);
- vq->vq_ring_mem = (void *)ring->phy_addr;
- vring_init(&vq->vq_ring, vq->vq_nentries, vq->vq_ring_mem, (uint32_t)vq->vq_alignment);
- *v_queue = vq;
- }
- return (status);
- }
- #else
- /*!
- * virtqueue_create - Creates new VirtIO queue
- *
- * @param id - VirtIO queue ID , must be unique
- * @param name - Name of VirtIO queue
- * @param ring - Pointer to vring_alloc_info control block
- * @param callback - Pointer to callback function, invoked
- * when message is available on VirtIO queue
- * @param notify - Pointer to notify function, used to notify
- * other side that there is job available for it
- * @param v_queue - Created VirtIO queue.
- *
- * @return - Function status
- */
- int32_t virtqueue_create(uint16_t id,
- const char *name,
- struct vring_alloc_info *ring,
- void (*callback_fc)(struct virtqueue *vq),
- void (*notify_fc)(struct virtqueue *vq),
- struct virtqueue **v_queue)
- {
- struct virtqueue *vq = VQ_NULL;
- volatile int32_t status = VQUEUE_SUCCESS;
- uint32_t vq_size = 0U;
- VQ_PARAM_CHK(ring == VQ_NULL, status, ERROR_VQUEUE_INVLD_PARAM);
- VQ_PARAM_CHK(ring->num_descs == 0U, status, ERROR_VQUEUE_INVLD_PARAM);
- VQ_PARAM_CHK(ring->num_descs & (ring->num_descs - 1U), status, ERROR_VRING_ALIGN);
- if (status == VQUEUE_SUCCESS)
- {
- vq_size = sizeof(struct virtqueue);
- vq = (struct virtqueue *)env_allocate_memory(vq_size);
- if (vq == VQ_NULL)
- {
- return (ERROR_NO_MEM);
- }
- env_memset(vq, 0x00, vq_size);
- env_strncpy(vq->vq_name, name, VIRTQUEUE_MAX_NAME_SZ);
- vq->vq_queue_index = id;
- vq->vq_alignment = (int32_t)(ring->align);
- vq->vq_nentries = ring->num_descs;
- vq->callback_fc = callback_fc;
- vq->notify_fc = notify_fc;
- // indirect addition is not supported
- vq->vq_ring_size = vring_size(ring->num_descs, ring->align);
- vq->vq_ring_mem = (void *)ring->phy_addr;
- vring_init(&vq->vq_ring, vq->vq_nentries, vq->vq_ring_mem, (uint32_t)vq->vq_alignment);
- *v_queue = vq;
- }
- return (status);
- }
- #endif /* RL_USE_STATIC_API */
- /*!
- * virtqueue_add_buffer() - Enqueues new buffer in vring for consumption
- * by other side.
- *
- * @param vq - Pointer to VirtIO queue control block.
- * @param head_idx - Index of buffer to be added to the avail ring
- *
- * @return - Function status
- */
- int32_t virtqueue_add_buffer(struct virtqueue *vq, uint16_t head_idx)
- {
- volatile int32_t status = VQUEUE_SUCCESS;
- VQ_PARAM_CHK(vq == VQ_NULL, status, ERROR_VQUEUE_INVLD_PARAM);
- VQUEUE_BUSY(vq, avail_write);
- if (status == VQUEUE_SUCCESS)
- {
- VQ_RING_ASSERT_VALID_IDX(vq, head_idx);
- /*
- * Update vring_avail control block fields so that other
- * side can get buffer using it.
- */
- vq_ring_update_avail(vq, head_idx);
- }
- VQUEUE_IDLE(vq, avail_write);
- return (status);
- }
- /*!
- * virtqueue_fill_avail_buffers - Enqueues single buffer in vring, updates avail
- *
- * @param vq - Pointer to VirtIO queue control block
- * @param buffer - Address of buffer
- * @param len - Length of buffer
- *
- * @return - Function status
- */
- int32_t virtqueue_fill_avail_buffers(struct virtqueue *vq, void *buffer, uint32_t len)
- {
- struct vring_desc *dp;
- uint16_t head_idx;
- volatile int32_t status = VQUEUE_SUCCESS;
- VQ_PARAM_CHK(vq == VQ_NULL, status, ERROR_VQUEUE_INVLD_PARAM);
- VQUEUE_BUSY(vq, avail_write);
- if (status == VQUEUE_SUCCESS)
- {
- head_idx = vq->vq_desc_head_idx;
- dp = &vq->vq_ring.desc[head_idx];
- #if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1)
- dp->addr = env_map_vatopa(vq->env, buffer);
- #else
- dp->addr = env_map_vatopa(buffer);
- #endif
- dp->len = len;
- dp->flags = VRING_DESC_F_WRITE;
- vq->vq_desc_head_idx++;
- vq_ring_update_avail(vq, head_idx);
- }
- VQUEUE_IDLE(vq, avail_write);
- return (status);
- }
- /*!
- * virtqueue_get_buffer - Returns used buffers from VirtIO queue
- *
- * @param vq - Pointer to VirtIO queue control block
- * @param len - Length of consumed buffer
- * @param idx - Index to buffer descriptor pool
- *
- * @return - Pointer to used buffer
- */
- void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx)
- {
- struct vring_used_elem *uep;
- uint16_t used_idx, desc_idx;
- if ((vq == VQ_NULL) || (vq->vq_used_cons_idx == vq->vq_ring.used->idx))
- {
- return (VQ_NULL);
- }
- VQUEUE_BUSY(vq, used_read);
- used_idx = (uint16_t)(vq->vq_used_cons_idx & ((uint16_t)(vq->vq_nentries - 1U)));
- uep = &vq->vq_ring.used->ring[used_idx];
- env_rmb();
- desc_idx = (uint16_t)uep->id;
- if (len != VQ_NULL)
- {
- *len = uep->len;
- }
- if (idx != VQ_NULL)
- {
- *idx = desc_idx;
- }
- vq->vq_used_cons_idx++;
- VQUEUE_IDLE(vq, used_read);
- #if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1)
- return env_map_patova(vq->env, ((uint32_t)(vq->vq_ring.desc[desc_idx].addr)));
- #else
- return env_map_patova((uint32_t)(vq->vq_ring.desc[desc_idx].addr));
- #endif
- }
- /*!
- * virtqueue_get_buffer_length - Returns size of a buffer
- *
- * @param vq - Pointer to VirtIO queue control block
- * @param idx - Index to buffer descriptor pool
- *
- * @return - Buffer length
- */
- uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx)
- {
- return vq->vq_ring.desc[idx].len;
- }
- #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
- /*!
- * virtqueue_free - Frees VirtIO queue resources - static version
- *
- * @param vq - Pointer to VirtIO queue control block
- *
- */
- void virtqueue_free_static(struct virtqueue *vq)
- {
- if (vq != VQ_NULL)
- {
- if (vq->vq_ring_mem != VQ_NULL)
- {
- vq->vq_ring_size = 0;
- vq->vq_ring_mem = VQ_NULL;
- }
- }
- }
- #else
- /*!
- * virtqueue_free - Frees VirtIO queue resources
- *
- * @param vq - Pointer to VirtIO queue control block
- *
- */
- void virtqueue_free(struct virtqueue *vq)
- {
- if (vq != VQ_NULL)
- {
- if (vq->vq_ring_mem != VQ_NULL)
- {
- vq->vq_ring_size = 0;
- vq->vq_ring_mem = VQ_NULL;
- }
- env_free_memory(vq);
- }
- }
- #endif /* RL_USE_STATIC_API */
- /*!
- * virtqueue_get_available_buffer - Returns buffer available for use in the
- * VirtIO queue
- *
- * @param vq - Pointer to VirtIO queue control block
- * @param avail_idx - Pointer to index used in vring desc table
- * @param len - Length of buffer
- *
- * @return - Pointer to available buffer
- */
- void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx, uint32_t *len)
- {
- uint16_t head_idx = 0;
- void *buffer;
- if (vq->vq_available_idx == vq->vq_ring.avail->idx)
- {
- return (VQ_NULL);
- }
- VQUEUE_BUSY(vq, avail_read);
- head_idx = (uint16_t)(vq->vq_available_idx++ & ((uint16_t)(vq->vq_nentries - 1U)));
- *avail_idx = vq->vq_ring.avail->ring[head_idx];
- env_rmb();
- #if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1)
- buffer = env_map_patova(vq->env, ((uint32_t)(vq->vq_ring.desc[*avail_idx].addr)));
- #else
- buffer = env_map_patova((uint32_t)(vq->vq_ring.desc[*avail_idx].addr));
- #endif
- *len = vq->vq_ring.desc[*avail_idx].len;
- VQUEUE_IDLE(vq, avail_read);
- return (buffer);
- }
- /*!
- * virtqueue_add_consumed_buffer - Returns consumed buffer back to VirtIO queue
- *
- * @param vq - Pointer to VirtIO queue control block
- * @param head_idx - Index of vring desc containing used buffer
- * @param len - Length of buffer
- *
- * @return - Function status
- */
- int32_t virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx, uint32_t len)
- {
- if (head_idx > vq->vq_nentries)
- {
- return (ERROR_VRING_NO_BUFF);
- }
- VQUEUE_BUSY(vq, used_write);
- vq_ring_update_used(vq, head_idx, len);
- VQUEUE_IDLE(vq, used_write);
- return (VQUEUE_SUCCESS);
- }
- /*!
- * virtqueue_fill_used_buffers - Fill used buffer ring
- *
- * @param vq - Pointer to VirtIO queue control block
- * @param buffer - Buffer to add
- * @param len - Length of buffer
- *
- * @return - Function status
- */
- int32_t virtqueue_fill_used_buffers(struct virtqueue *vq, void *buffer, uint32_t len)
- {
- uint16_t head_idx;
- uint16_t idx;
- VQUEUE_BUSY(vq, used_write);
- head_idx = vq->vq_desc_head_idx;
- VQ_RING_ASSERT_VALID_IDX(vq, head_idx);
- /* Enqueue buffer onto the ring. */
- idx = vq_ring_add_buffer(vq, vq->vq_ring.desc, head_idx, buffer, len);
- vq->vq_desc_head_idx = idx;
- vq_ring_update_used(vq, head_idx, len);
- VQUEUE_IDLE(vq, used_write);
- return (VQUEUE_SUCCESS);
- }
- /*!
- * virtqueue_enable_cb - Enables callback generation
- *
- * @param vq - Pointer to VirtIO queue control block
- *
- * @return - Function status
- */
- int32_t virtqueue_enable_cb(struct virtqueue *vq)
- {
- /* coco begin validated: This virtqueue function does not need to be tested because it is not used in rpmsg_lite
- * implementation */
- return (vq_ring_enable_interrupt(vq, 0));
- }
- /* coco end */
- /*!
- * virtqueue_enable_cb - Disables callback generation
- *
- * @param vq - Pointer to VirtIO queue control block
- *
- */
- void virtqueue_disable_cb(struct virtqueue *vq)
- {
- VQUEUE_BUSY(vq, avail_write);
- if ((vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) != 0UL)
- {
- /* coco begin validated: This part does not need to be tested because VIRTQUEUE_FLAG_EVENT_IDX is not being
- * utilized in rpmsg_lite implementation */
- vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx - vq->vq_nentries - 1U;
- }
- /* coco end */
- else
- {
- vq->vq_ring.avail->flags |= (uint16_t)VRING_AVAIL_F_NO_INTERRUPT;
- }
- VQUEUE_IDLE(vq, avail_write);
- }
- /*!
- * virtqueue_kick - Notifies other side that there is buffer available for it.
- *
- * @param vq - Pointer to VirtIO queue control block
- */
- void virtqueue_kick(struct virtqueue *vq)
- {
- VQUEUE_BUSY(vq, avail_write);
- /* Ensure updated avail->idx is visible to host. */
- env_mb();
- if (0 != vq_ring_must_notify_host(vq))
- {
- vq_ring_notify_host(vq);
- }
- vq->vq_queued_cnt = 0;
- VQUEUE_IDLE(vq, avail_write);
- }
- /*!
- * virtqueue_dump Dumps important virtqueue fields , use for debugging purposes
- *
- * @param vq - Pointer to VirtIO queue control block
- */
- void virtqueue_dump(struct virtqueue *vq)
- {
- /* coco begin validated: This virtqueue function does not need to be tested because it is not used in rpmsg_lite
- * implementation */
- if (vq == VQ_NULL)
- {
- return;
- }
- env_print(
- "VQ: %s - size=%d; used=%d; queued=%d; "
- "desc_head_idx=%d; avail.idx=%d; used_cons_idx=%d; "
- "used.idx=%d; avail.flags=0x%x; used.flags=0x%x\r\n",
- vq->vq_name, vq->vq_nentries, virtqueue_nused(vq), vq->vq_queued_cnt, vq->vq_desc_head_idx,
- vq->vq_ring.avail->idx, vq->vq_used_cons_idx, vq->vq_ring.used->idx, vq->vq_ring.avail->flags,
- vq->vq_ring.used->flags);
- }
- /* coco end */
- /*!
- * virtqueue_get_desc_size - Returns vring descriptor size
- *
- * @param vq - Pointer to VirtIO queue control block
- *
- * @return - Descriptor length
- */
- uint32_t virtqueue_get_desc_size(struct virtqueue *vq)
- {
- /* coco begin validated: This virtqueue function does not need to be tested because it is not used in rpmsg_lite
- * implementation */
- uint16_t head_idx;
- uint16_t avail_idx;
- uint32_t len;
- if (vq->vq_available_idx == vq->vq_ring.avail->idx)
- {
- return 0;
- }
- head_idx = (uint16_t)(vq->vq_available_idx & ((uint16_t)(vq->vq_nentries - 1U)));
- avail_idx = vq->vq_ring.avail->ring[head_idx];
- len = vq->vq_ring.desc[avail_idx].len;
- return (len);
- }
- /* coco end */
- /**************************************************************************
- * Helper Functions *
- **************************************************************************/
- /*!
- *
- * vq_ring_add_buffer
- *
- */
- static uint16_t vq_ring_add_buffer(
- struct virtqueue *vq, struct vring_desc *desc, uint16_t head_idx, void *buffer, uint32_t length)
- {
- struct vring_desc *dp;
- if (buffer == VQ_NULL)
- {
- return head_idx; /* coco validated: line never reached, vq_ring_add_buffer() is called from
- rpmsg_lite_master_init() only and the buffer parameter not being null check is done before
- passing the parameter */
- }
- VQASSERT(vq, head_idx != VQ_RING_DESC_CHAIN_END, "premature end of free desc chain");
- dp = &desc[head_idx];
- #if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1)
- dp->addr = env_map_vatopa(vq->env, buffer);
- #else
- dp->addr = env_map_vatopa(buffer);
- #endif
- dp->len = length;
- dp->flags = VRING_DESC_F_WRITE;
- return (head_idx + 1U);
- }
- /*!
- *
- * vq_ring_init
- *
- */
- void vq_ring_init(struct virtqueue *vq)
- {
- struct vring *vr;
- uint32_t i, size;
- size = (uint32_t)(vq->vq_nentries);
- vr = &vq->vq_ring;
- for (i = 0U; i < size - 1U; i++)
- {
- vr->desc[i].next = (uint16_t)(i + 1U);
- }
- vr->desc[i].next = (uint16_t)VQ_RING_DESC_CHAIN_END;
- }
- /*!
- *
- * vq_ring_update_avail
- *
- */
- static void vq_ring_update_avail(struct virtqueue *vq, uint16_t desc_idx)
- {
- uint16_t avail_idx;
- /*
- * Place the head of the descriptor chain into the next slot and make
- * it usable to the host. The chain is made available now rather than
- * deferring to virtqueue_notify() in the hopes that if the host is
- * currently running on another CPU, we can keep it processing the new
- * descriptor.
- */
- avail_idx = (uint16_t)(vq->vq_ring.avail->idx & ((uint16_t)(vq->vq_nentries - 1U)));
- vq->vq_ring.avail->ring[avail_idx] = desc_idx;
- env_wmb();
- vq->vq_ring.avail->idx++;
- /* Keep pending count until virtqueue_notify(). */
- vq->vq_queued_cnt++;
- }
- /*!
- *
- * vq_ring_update_used
- *
- */
- static void vq_ring_update_used(struct virtqueue *vq, uint16_t head_idx, uint32_t len)
- {
- uint16_t used_idx;
- struct vring_used_elem *used_desc = VQ_NULL;
- /*
- * Place the head of the descriptor chain into the next slot and make
- * it usable to the host. The chain is made available now rather than
- * deferring to virtqueue_notify() in the hopes that if the host is
- * currently running on another CPU, we can keep it processing the new
- * descriptor.
- */
- used_idx = vq->vq_ring.used->idx & (vq->vq_nentries - 1U);
- used_desc = &(vq->vq_ring.used->ring[used_idx]);
- used_desc->id = head_idx;
- used_desc->len = len;
- env_wmb();
- vq->vq_ring.used->idx++;
- }
- /*!
- *
- * vq_ring_enable_interrupt
- *
- */
- static int32_t vq_ring_enable_interrupt(struct virtqueue *vq, uint16_t ndesc)
- {
- /* coco begin validated: This virtqueue function does not need to be tested because it is not used in rpmsg_lite
- * implementation */
- /*
- * Enable interrupts, making sure we get the latest index of
- * what's already been consumed.
- */
- if ((vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) != 0UL)
- {
- vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx + ndesc;
- }
- else
- {
- vq->vq_ring.avail->flags &= ~(uint16_t)VRING_AVAIL_F_NO_INTERRUPT;
- }
- env_mb();
- /*
- * Enough items may have already been consumed to meet our threshold
- * since we last checked. Let our caller know so it processes the new
- * entries.
- */
- if (virtqueue_nused(vq) > ndesc)
- {
- return (1);
- }
- return (0);
- }
- /* coco end */
- /*!
- *
- * virtqueue_interrupt
- *
- */
- void virtqueue_notification(struct virtqueue *vq)
- {
- if (vq != VQ_NULL)
- {
- if (vq->callback_fc != VQ_NULL)
- {
- vq->callback_fc(vq);
- }
- }
- }
- /*!
- *
- * vq_ring_must_notify_host
- *
- */
- static int32_t vq_ring_must_notify_host(struct virtqueue *vq)
- {
- uint16_t new_idx, prev_idx;
- uint16_t event_idx;
- if ((vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) != 0UL)
- {
- /* coco begin validated: This part does not need to be tested because VIRTQUEUE_FLAG_EVENT_IDX is not being
- * utilized in rpmsg_lite implementation */
- new_idx = vq->vq_ring.avail->idx;
- prev_idx = new_idx - vq->vq_queued_cnt;
- event_idx = (uint16_t)vring_avail_event(&vq->vq_ring);
- return ((vring_need_event(event_idx, new_idx, prev_idx) != 0) ? 1 : 0);
- }
- /* coco end */
- return (((vq->vq_ring.used->flags & ((uint16_t)VRING_USED_F_NO_NOTIFY)) == 0U) ? 1 : 0);
- }
- /*!
- *
- * vq_ring_notify_host
- *
- */
- static void vq_ring_notify_host(struct virtqueue *vq)
- {
- if (vq->notify_fc != VQ_NULL)
- {
- vq->notify_fc(vq);
- }
- }
- /*!
- *
- * virtqueue_nused
- *
- */
- static uint16_t virtqueue_nused(struct virtqueue *vq)
- {
- /* coco begin validated: This virtqueue function does not need to be tested because it is not used in rpmsg_lite
- * implementation */
- uint16_t used_idx, nused;
- used_idx = vq->vq_ring.used->idx;
- nused = (uint16_t)(used_idx - vq->vq_used_cons_idx);
- VQASSERT(vq, nused <= vq->vq_nentries, "used more than available");
- return (nused);
- }
- /* coco end */
|