During odp_schedule_release_ordered() processing in order elements
on a reorder queue should be processed even if they are marked sustain
since no further elements with the current order will be enqueued.
This fixes Bug https://bugs.linaro.org/show_bug.cgi?id=1824
Signed-off-by: Bill Fischofer <bill.fischo...@linaro.org>
---
platform/linux-generic/include/odp_queue_internal.h | 5 +++--
platform/linux-generic/odp_queue.c | 18 +++++++++++-------
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/platform/linux-generic/include/odp_queue_internal.h
b/platform/linux-generic/include/odp_queue_internal.h
index c322e6a..6322948 100644
--- a/platform/linux-generic/include/odp_queue_internal.h
+++ b/platform/linux-generic/include/odp_queue_internal.h
@@ -291,7 +291,8 @@ static inline int reorder_deq(queue_entry_t *queue,
static inline void reorder_complete(queue_entry_t *origin_qe,
odp_buffer_hdr_t **reorder_buf_return,
odp_buffer_hdr_t **placeholder_buf,
- int placeholder_append)
+ int placeholder_append,
+ int order_released)
{
odp_buffer_hdr_t *reorder_buf = origin_qe->s.reorder_head;
odp_buffer_hdr_t *next_buf;
@@ -311,7 +312,7 @@ static inline void reorder_complete(queue_entry_t
*origin_qe,
reorder_buf = next_buf;
order_release(origin_qe, 1);
- } else if (reorder_buf->flags.sustain) {
+ } else if (!order_released && reorder_buf->flags.sustain) {
reorder_buf = next_buf;
} else {
*reorder_buf_return = origin_qe->s.reorder_head;
diff --git a/platform/linux-generic/odp_queue.c
b/platform/linux-generic/odp_queue.c
index a7022cf..a27af0b 100644
--- a/platform/linux-generic/odp_queue.c
+++ b/platform/linux-generic/odp_queue.c
@@ -478,7 +478,8 @@ int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t
*buf_hdr, int sustain)
* other queues, appending placeholder bufs as needed.
*/
UNLOCK(&queue->s.lock);
- reorder_complete(origin_qe, &reorder_buf, &placeholder_buf, 1);
+ reorder_complete(origin_qe, &reorder_buf, &placeholder_buf,
+ 1, 0);
UNLOCK(&origin_qe->s.lock);
if (reorder_buf)
@@ -844,7 +845,7 @@ int queue_pktout_enq(queue_entry_t *queue, odp_buffer_hdr_t
*buf_hdr,
order_release(origin_qe, release_count + placeholder_count);
/* Now handle sends to other queues that are ready to go */
- reorder_complete(origin_qe, &reorder_buf, &placeholder_buf, 1);
+ reorder_complete(origin_qe, &reorder_buf, &placeholder_buf, 1, 0);
/* We're fully done with the origin_qe at last */
UNLOCK(&origin_qe->s.lock);
@@ -921,13 +922,16 @@ int release_order(queue_entry_t *origin_qe, uint64_t
order,
if (order <= origin_qe->s.order_out) {
order_release(origin_qe, 1);
- /* Check if this release allows us to unblock waiters.
- * At the point of this call, the reorder list may contain
- * zero or more placeholders that need to be freed, followed
- * by zero or one complete reorder buffer chain.
+ /* Check if this release allows us to unblock waiters. At the
+ * point of this call, the reorder list may contain zero or
+ * more placeholders that need to be freed, followed by zero
+ * or one complete reorder buffer chain. Note that since we
+ * are releasing order, we know no further enqs for this order
+ * can occur, so ignore the sustain bit to clear out our
+ * element(s) on the reorder queue
*/
reorder_complete(origin_qe, &reorder_buf,
- &placeholder_buf_hdr, 0);
+ &placeholder_buf_hdr, 0, 1);
/* Now safe to unlock */
UNLOCK(&origin_qe->s.lock);