src/dpdk/drivers/net/mlx5/mlx5_trigger.c
int
mlx5_hairpin_queue_peer_bind(struct rte_eth_dev *dev, uint16_t cur_queue,
			     struct rte_hairpin_peer_info *peer_info,
			     uint32_t direction)
{
	int ret = 0;

	/*
	 * Consistency checking of the peer queue: opposite direction is used
	 * to get the peer queue info with ethdev port ID, no need to check.
	 */
	if (peer_info->peer_q != cur_queue) {
		rte_errno = EINVAL;
		DRV_LOG(ERR, "port %u queue %d and peer queue %d mismatch",
			dev->data->port_id, cur_queue, peer_info->peer_q);
		return -rte_errno;
	}
	if (direction != 0) {
		struct mlx5_txq_ctrl *txq_ctrl;
		struct mlx5_devx_modify_sq_attr sq_attr = { 0 };

		txq_ctrl = mlx5_txq_get(dev, cur_queue);
		if (txq_ctrl == NULL) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "Failed to get port %u Tx queue %d",
				dev->data->port_id, cur_queue);
			return -rte_errno;
		}
		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u queue %d not a hairpin Txq",
				dev->data->port_id, cur_queue);
			mlx5_txq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (txq_ctrl->obj == NULL || txq_ctrl->obj->sq == NULL) {
			rte_errno = ENOMEM;
			DRV_LOG(ERR, "port %u no Txq object found: %d",
				dev->data->port_id, cur_queue);
			mlx5_txq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (txq_ctrl->hairpin_status != 0) {
			DRV_LOG(DEBUG, "port %u Tx queue %d is already bound",
				dev->data->port_id, cur_queue);
			mlx5_txq_release(dev, cur_queue);
			return 0;
		}
		/*
		 * All queues' of one port consistency checking is done in the
		 * bind() function, and that is optional.
		 */
		if (peer_info->tx_explicit !=
		    txq_ctrl->hairpin_conf.tx_explicit) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u Tx queue %d and peer Tx rule mode"
				" mismatch", dev->data->port_id, cur_queue);
			mlx5_txq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (peer_info->manual_bind !=
		    txq_ctrl->hairpin_conf.manual_bind) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u Tx queue %d and peer binding mode"
				" mismatch", dev->data->port_id, cur_queue);
			mlx5_txq_release(dev, cur_queue);
			return -rte_errno;
		}
		sq_attr.state = MLX5_SQC_STATE_RDY;
		sq_attr.sq_state = MLX5_SQC_STATE_RST;
		sq_attr.hairpin_peer_rq = peer_info->qp_id;
		sq_attr.hairpin_peer_vhca = peer_info->vhca_id;
		ret = mlx5_devx_cmd_modify_sq(txq_ctrl->obj->sq, &sq_attr);
		if (ret == 0)
			txq_ctrl->hairpin_status = 1;
		mlx5_txq_release(dev, cur_queue);
	} else {
		struct mlx5_rxq_ctrl *rxq_ctrl;
		struct mlx5_devx_modify_rq_attr rq_attr = { 0 };

		rxq_ctrl = mlx5_rxq_get(dev, cur_queue);
		if (rxq_ctrl == NULL) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "Failed to get port %u Rx queue %d",
				dev->data->port_id, cur_queue);
			return -rte_errno;
		}
		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u queue %d not a hairpin Rxq",
				dev->data->port_id, cur_queue);
			mlx5_rxq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (rxq_ctrl->obj == NULL || rxq_ctrl->obj->rq == NULL) {
			rte_errno = ENOMEM;
			DRV_LOG(ERR, "port %u no Rxq object found: %d",
				dev->data->port_id, cur_queue);
			mlx5_rxq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (rxq_ctrl->hairpin_status != 0) {
			DRV_LOG(DEBUG, "port %u Rx queue %d is already bound",
				dev->data->port_id, cur_queue);
			mlx5_rxq_release(dev, cur_queue);
			return 0;
		}
		if (peer_info->tx_explicit !=
		    rxq_ctrl->hairpin_conf.tx_explicit) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u Rx queue %d and peer Tx rule mode"
				" mismatch", dev->data->port_id, cur_queue);
			mlx5_rxq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (peer_info->manual_bind !=
		    rxq_ctrl->hairpin_conf.manual_bind) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u Rx queue %d and peer binding mode"
				" mismatch", dev->data->port_id, cur_queue);
			mlx5_rxq_release(dev, cur_queue);
			return -rte_errno;
		}
		rq_attr.state = MLX5_SQC_STATE_RDY;
		rq_attr.rq_state = MLX5_SQC_STATE_RST;
		rq_attr.hairpin_peer_sq = peer_info->qp_id;
		rq_attr.hairpin_peer_vhca = peer_info->vhca_id;
		ret = mlx5_devx_cmd_modify_rq(rxq_ctrl->obj->rq, &rq_attr);
		if (ret == 0)
			rxq_ctrl->hairpin_status = 1;
		mlx5_rxq_release(dev, cur_queue);
	}
	return ret;
}
/*
 * Bind the hairpin queue with the peer HW information.
 * This needs to be called twice both for Tx and Rx queues of a pair.
 * If the queue is already bound, it is considered successful.
 *
 * @param dev
 *   Pointer to Ethernet device structure.
 * @param cur_queue
 *   Index of the queue to change the HW configuration to bind.
 * @param peer_info
 *   Pointer to information of the peer queue.
 * @param direction
 *   Positive to configure the TxQ, zero to configure the RxQ.
 *
 * @return
 *   0 on success, a negative errno value otherwise and rte_errno is set.
 */
Bind the hairpin queue with the peer HW information.
This needs to be called twice both for Tx and Rx queues of a pair.
If the queue is already bound, it is considered successful.

@param dev
Pointer to Ethernet device structure.
@param cur_queue
Index of the queue to change the HW configuration to bind.
@param peer_info
Pointer to information of the peer queue.
@param direction
Positive to configure the TxQ, zero to configure the RxQ.

@return
0 on success, a negative errno value otherwise and rte_errno is set.
Bind the hairpin queue with the peer HW information . This needs to be called twice both for Tx and Rx queues of a pair . If the queue is already bound it is considered successful . @param dev Pointer to Ethernet device structure . @param cur_queue Index of the queue to change the HW configuration to bind . @param peer_info Pointer to information of the peer queue . @param direction Positive to configure the TxQ zero to configure the RxQ . @return 0 on success a negative errno value otherwise and rte_errno is set .
int
mlx5_hairpin_queue_peer_bind(struct rte_eth_dev *dev, uint16_t cur_queue,
			     struct rte_hairpin_peer_info *peer_info,
			     uint32_t direction)
{
	int ret = 0;
	if (peer_info->peer_q != cur_queue) {
		rte_errno = EINVAL;
		DRV_LOG(ERR, "port %u queue %d and peer queue %d mismatch",
			dev->data->port_id, cur_queue, peer_info->peer_q);
		return -rte_errno;
	}
	if (direction != 0) {
		struct mlx5_txq_ctrl *txq_ctrl;
		struct mlx5_devx_modify_sq_attr sq_attr = { 0 };
		txq_ctrl = mlx5_txq_get(dev, cur_queue);
		if (txq_ctrl == NULL) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "Failed to get port %u Tx queue %d",
				dev->data->port_id, cur_queue);
			return -rte_errno;
		}
		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u queue %d not a hairpin Txq",
				dev->data->port_id, cur_queue);
			mlx5_txq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (txq_ctrl->obj == NULL || txq_ctrl->obj->sq == NULL) {
			rte_errno = ENOMEM;
			DRV_LOG(ERR, "port %u no Txq object found: %d",
				dev->data->port_id, cur_queue);
			mlx5_txq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (txq_ctrl->hairpin_status != 0) {
			DRV_LOG(DEBUG, "port %u Tx queue %d is already bound",
				dev->data->port_id, cur_queue);
			mlx5_txq_release(dev, cur_queue);
			return 0;
		}
		if (peer_info->tx_explicit !=
		    txq_ctrl->hairpin_conf.tx_explicit) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u Tx queue %d and peer Tx rule mode"
				" mismatch", dev->data->port_id, cur_queue);
			mlx5_txq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (peer_info->manual_bind !=
		    txq_ctrl->hairpin_conf.manual_bind) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u Tx queue %d and peer binding mode"
				" mismatch", dev->data->port_id, cur_queue);
			mlx5_txq_release(dev, cur_queue);
			return -rte_errno;
		}
		sq_attr.state = MLX5_SQC_STATE_RDY;
		sq_attr.sq_state = MLX5_SQC_STATE_RST;
		sq_attr.hairpin_peer_rq = peer_info->qp_id;
		sq_attr.hairpin_peer_vhca = peer_info->vhca_id;
		ret = mlx5_devx_cmd_modify_sq(txq_ctrl->obj->sq, &sq_attr);
		if (ret == 0)
			txq_ctrl->hairpin_status = 1;
		mlx5_txq_release(dev, cur_queue);
	} else {
		struct mlx5_rxq_ctrl *rxq_ctrl;
		struct mlx5_devx_modify_rq_attr rq_attr = { 0 };
		rxq_ctrl = mlx5_rxq_get(dev, cur_queue);
		if (rxq_ctrl == NULL) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "Failed to get port %u Rx queue %d",
				dev->data->port_id, cur_queue);
			return -rte_errno;
		}
		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u queue %d not a hairpin Rxq",
				dev->data->port_id, cur_queue);
			mlx5_rxq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (rxq_ctrl->obj == NULL || rxq_ctrl->obj->rq == NULL) {
			rte_errno = ENOMEM;
			DRV_LOG(ERR, "port %u no Rxq object found: %d",
				dev->data->port_id, cur_queue);
			mlx5_rxq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (rxq_ctrl->hairpin_status != 0) {
			DRV_LOG(DEBUG, "port %u Rx queue %d is already bound",
				dev->data->port_id, cur_queue);
			mlx5_rxq_release(dev, cur_queue);
			return 0;
		}
		if (peer_info->tx_explicit !=
		    rxq_ctrl->hairpin_conf.tx_explicit) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u Rx queue %d and peer Tx rule mode"
				" mismatch", dev->data->port_id, cur_queue);
			mlx5_rxq_release(dev, cur_queue);
			return -rte_errno;
		}
		if (peer_info->manual_bind !=
		    rxq_ctrl->hairpin_conf.manual_bind) {
			rte_errno = EINVAL;
			DRV_LOG(ERR, "port %u Rx queue %d and peer binding mode"
				" mismatch", dev->data->port_id, cur_queue);
			mlx5_rxq_release(dev, cur_queue);
			return -rte_errno;
		}
		rq_attr.state = MLX5_SQC_STATE_RDY;
		rq_attr.rq_state = MLX5_SQC_STATE_RST;
		rq_attr.hairpin_peer_sq = peer_info->qp_id;
		rq_attr.hairpin_peer_vhca = peer_info->vhca_id;
		ret = mlx5_devx_cmd_modify_rq(rxq_ctrl->obj->rq, &rq_attr);
		if (ret == 0)
			rxq_ctrl->hairpin_status = 1;
		mlx5_rxq_release(dev, cur_queue);
	}
	return ret;
}
int mlx5_hairpin_queue_peer_bind ( struct rte_eth_dev * dev , uint16_t cur_queue , struct rte_hairpin_peer_info * peer_info , uint32_t direction ) { int ret = 0 ; if ( peer_info -> peer_q != cur_queue ) { rte_errno = EINVAL ; DRV_LOG ( ERR , " " , dev -> data -> port_id , cur_queue , peer_info -> peer_q ) ; return - rte_errno ; } if ( direction != 0 ) { struct mlx5_txq_ctrl * txq_ctrl ; struct mlx5_devx_modify_sq_attr sq_attr = { 0 } ; txq_ctrl = mlx5_txq_get ( dev , cur_queue ) ; if ( txq_ctrl == NULL ) { rte_errno = EINVAL ; DRV_LOG ( ERR , " " , dev -> data -> port_id , cur_queue ) ; return - rte_errno ; } if ( txq_ctrl -> type != MLX5_TXQ_TYPE_HAIRPIN ) { rte_errno = EINVAL ; DRV_LOG ( ERR , " " , dev -> data -> port_id , cur_queue ) ; mlx5_txq_release ( dev , cur_queue ) ; return - rte_errno ; } if ( txq_ctrl -> obj == NULL || txq_ctrl -> obj -> sq == NULL ) { rte_errno = ENOMEM ; DRV_LOG ( ERR , " " , dev -> data -> port_id , cur_queue ) ; mlx5_txq_release ( dev , cur_queue ) ; return - rte_errno ; } if ( txq_ctrl -> hairpin_status != 0 ) { DRV_LOG ( DEBUG , " " , dev -> data -> port_id , cur_queue ) ; mlx5_txq_release ( dev , cur_queue ) ; return 0 ; } if ( peer_info -> tx_explicit != txq_ctrl -> hairpin_conf . tx_explicit ) { rte_errno = EINVAL ; DRV_LOG ( ERR , " " " " , dev -> data -> port_id , cur_queue ) ; mlx5_txq_release ( dev , cur_queue ) ; return - rte_errno ; } if ( peer_info -> manual_bind != txq_ctrl -> hairpin_conf . manual_bind ) { rte_errno = EINVAL ; DRV_LOG ( ERR , " " " " , dev -> data -> port_id , cur_queue ) ; mlx5_txq_release ( dev , cur_queue ) ; return - rte_errno ; } sq_attr . state = MLX5_SQC_STATE_RDY ; sq_attr . sq_state = MLX5_SQC_STATE_RST ; sq_attr . hairpin_peer_rq = peer_info -> qp_id ; sq_attr . hairpin_peer_vhca = peer_info -> vhca_id ; ret = mlx5_devx_cmd_modify_sq ( txq_ctrl -> obj -> sq , & sq_attr ) ; if ( ret == 0 ) txq_ctrl -> hairpin_status = 1 ; mlx5_txq_release ( dev , cur_queue ) ; } else { struct mlx5_rxq_ctrl * rxq_ctrl ; struct mlx5_devx_modify_rq_attr rq_attr = { 0 } ; rxq_ctrl = mlx5_rxq_get ( dev , cur_queue ) ; if ( rxq_ctrl == NULL ) { rte_errno = EINVAL ; DRV_LOG ( ERR , " " , dev -> data -> port_id , cur_queue ) ; return - rte_errno ; } if ( rxq_ctrl -> type != MLX5_RXQ_TYPE_HAIRPIN ) { rte_errno = EINVAL ; DRV_LOG ( ERR , " " , dev -> data -> port_id , cur_queue ) ; mlx5_rxq_release ( dev , cur_queue ) ; return - rte_errno ; } if ( rxq_ctrl -> obj == NULL || rxq_ctrl -> obj -> rq == NULL ) { rte_errno = ENOMEM ; DRV_LOG ( ERR , " " , dev -> data -> port_id , cur_queue ) ; mlx5_rxq_release ( dev , cur_queue ) ; return - rte_errno ; } if ( rxq_ctrl -> hairpin_status != 0 ) { DRV_LOG ( DEBUG , " " , dev -> data -> port_id , cur_queue ) ; mlx5_rxq_release ( dev , cur_queue ) ; return 0 ; } if ( peer_info -> tx_explicit != rxq_ctrl -> hairpin_conf . tx_explicit ) { rte_errno = EINVAL ; DRV_LOG ( ERR , " " " " , dev -> data -> port_id , cur_queue ) ; mlx5_rxq_release ( dev , cur_queue ) ; return - rte_errno ; } if ( peer_info -> manual_bind != rxq_ctrl -> hairpin_conf . manual_bind ) { rte_errno = EINVAL ; DRV_LOG ( ERR , " " " " , dev -> data -> port_id , cur_queue ) ; mlx5_rxq_release ( dev , cur_queue ) ; return - rte_errno ; } rq_attr . state = MLX5_SQC_STATE_RDY ; rq_attr . rq_state = MLX5_SQC_STATE_RST ; rq_attr . hairpin_peer_sq = peer_info -> qp_id ; rq_attr . hairpin_peer_vhca = peer_info -> vhca_id ; ret = mlx5_devx_cmd_modify_rq ( rxq_ctrl -> obj -> rq , & rq_attr ) ; if ( ret == 0 ) rxq_ctrl -> hairpin_status = 1 ; mlx5_rxq_release ( dev , cur_queue ) ; } return ret ; }
Bind the hairpin queue with the peer HW information.
Bind the hairpin queue with the peer HW information .
/*
	 * Consistency checking of the peer queue: opposite direction is used
	 * to get the peer queue info with ethdev port ID, no need to check.
	 */ /*
		 * All queues' of one port consistency checking is done in the
		 * bind() function, and that is optional.
		 */