+/* Create a queue used to store the data structure elements that can
+ * be freed later. This queue is referred to as 'defer queue'.
+ */
+struct rte_rcu_qsbr_dq *
+rte_rcu_qsbr_dq_create(const struct rte_rcu_qsbr_dq_parameters *params)
+{
+ struct rte_rcu_qsbr_dq *dq;
+ uint32_t qs_fifo_size;
+ unsigned int flags;
+
+ if (params == NULL || params->free_fn == NULL ||
+ params->v == NULL || params->name == NULL ||
+ params->size == 0 || params->esize == 0 ||
+ (params->esize % 4 != 0)) {
+ rte_log(RTE_LOG_ERR, rte_rcu_log_type,
+ "%s(): Invalid input parameter\n", __func__);
+ rte_errno = EINVAL;
+
+ return NULL;
+ }
+ /* If auto reclamation is configured, reclaim limit
+ * should be a valid value.
+ */
+ if ((params->trigger_reclaim_limit <= params->size) &&
+ (params->max_reclaim_size == 0)) {
+ rte_log(RTE_LOG_ERR, rte_rcu_log_type,
+ "%s(): Invalid input parameter, size = %u, trigger_reclaim_limit = %u, max_reclaim_size = %u\n",
+ __func__, params->size, params->trigger_reclaim_limit,
+ params->max_reclaim_size);
+ rte_errno = EINVAL;
+
+ return NULL;
+ }
+
+ dq = rte_zmalloc(NULL, sizeof(struct rte_rcu_qsbr_dq),
+ RTE_CACHE_LINE_SIZE);
+ if (dq == NULL) {
+ rte_errno = ENOMEM;
+
+ return NULL;
+ }
+
+ /* Decide the flags for the ring.
+ * If MT safety is requested, use RTS for ring enqueue as most
+ * use cases involve dq-enqueue happening on the control plane.
+ * Ring dequeue is always HTS due to the possibility of revert.
+ */
+ flags = RING_F_MP_RTS_ENQ;
+ if (params->flags & RTE_RCU_QSBR_DQ_MT_UNSAFE)
+ flags = RING_F_SP_ENQ;
+ flags |= RING_F_MC_HTS_DEQ;
+ /* round up qs_fifo_size to next power of two that is not less than
+ * max_size.
+ */
+ qs_fifo_size = rte_align32pow2(params->size + 1);
+ /* Add token size to ring element size */
+ dq->r = rte_ring_create_elem(params->name,
+ __RTE_QSBR_TOKEN_SIZE + params->esize,
+ qs_fifo_size, SOCKET_ID_ANY, flags);
+ if (dq->r == NULL) {
+ rte_log(RTE_LOG_ERR, rte_rcu_log_type,
+ "%s(): defer queue create failed\n", __func__);
+ rte_free(dq);
+ return NULL;
+ }
+
+ dq->v = params->v;
+ dq->size = params->size;
+ dq->esize = __RTE_QSBR_TOKEN_SIZE + params->esize;
+ dq->trigger_reclaim_limit = params->trigger_reclaim_limit;
+ dq->max_reclaim_size = params->max_reclaim_size;
+ dq->free_fn = params->free_fn;
+ dq->p = params->p;