+ struct mlx5_priv *priv = dev->data->dev_private;
+ int socket_id = dev->device->numa_node;
+ struct mlx5_rxq_priv *rxq;
+ struct mlx5_rxq_ctrl *rxq_ctrl = NULL;
+ struct mlx5_rxq_obj *rxq_obj = NULL;
+ int ret;
+
+ /*
+ * Initialize dummy control structures.
+ * They are required to hold pointers for cleanup
+ * and are only accessible via drop queue DevX objects.
+ */
+ rxq = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*rxq), 0, socket_id);
+ if (rxq == NULL) {
+ DRV_LOG(ERR, "Port %u could not allocate drop queue private",
+ dev->data->port_id);
+ rte_errno = ENOMEM;
+ goto error;
+ }
+ rxq_ctrl = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*rxq_ctrl),
+ 0, socket_id);
+ if (rxq_ctrl == NULL) {
+ DRV_LOG(ERR, "Port %u could not allocate drop queue control",
+ dev->data->port_id);
+ rte_errno = ENOMEM;
+ goto error;
+ }
+ rxq_obj = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*rxq_obj), 0, socket_id);
+ if (rxq_obj == NULL) {
+ DRV_LOG(ERR, "Port %u could not allocate drop queue object",
+ dev->data->port_id);
+ rte_errno = ENOMEM;
+ goto error;
+ }
+ rxq_obj->rxq_ctrl = rxq_ctrl;
+ rxq_ctrl->type = MLX5_RXQ_TYPE_STANDARD;
+ rxq_ctrl->sh = priv->sh;
+ rxq_ctrl->obj = rxq_obj;
+ rxq->ctrl = rxq_ctrl;
+ rxq->priv = priv;
+ LIST_INSERT_HEAD(&rxq_ctrl->owners, rxq, owner_entry);
+ /* Create CQ using DevX API. */
+ ret = mlx5_rxq_create_devx_cq_resources(rxq);
+ if (ret != 0) {
+ DRV_LOG(ERR, "Port %u drop queue CQ creation failed.",
+ dev->data->port_id);
+ goto error;
+ }
+ rxq_ctrl->rxq.delay_drop = 0;
+ /* Create RQ using DevX API. */
+ ret = mlx5_rxq_create_devx_rq_resources(rxq);
+ if (ret != 0) {
+ DRV_LOG(ERR, "Port %u drop queue RQ creation failed.",
+ dev->data->port_id);
+ rte_errno = ENOMEM;
+ goto error;
+ }
+ /* Change queue state to ready. */
+ ret = mlx5_devx_modify_rq(rxq, MLX5_RXQ_MOD_RST2RDY);
+ if (ret != 0)
+ goto error;
+ /* Initialize drop queue. */
+ priv->drop_queue.rxq = rxq;
+ return 0;
+error:
+ ret = rte_errno; /* Save rte_errno before cleanup. */
+ if (rxq != NULL && rxq->devx_rq.rq != NULL)
+ mlx5_devx_rq_destroy(&rxq->devx_rq);
+ if (rxq_obj != NULL) {
+ if (rxq_obj->cq_obj.cq != NULL)
+ mlx5_devx_cq_destroy(&rxq_obj->cq_obj);
+ if (rxq_obj->devx_channel)
+ mlx5_os_devx_destroy_event_channel
+ (rxq_obj->devx_channel);
+ mlx5_free(rxq_obj);
+ }
+ if (rxq_ctrl != NULL)
+ mlx5_free(rxq_ctrl);
+ if (rxq != NULL)
+ mlx5_free(rxq);
+ rte_errno = ret; /* Restore rte_errno. */