mlx5_rx_queue_lwm_set(struct rte_eth_dev *dev, uint16_t rx_queue_id,
		      uint8_t lwm)
{
	struct mlx5_priv *priv = dev->data->dev_private;
	uint16_t port_id = PORT_ID(priv);
	struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, rx_queue_id);
	uint16_t event_nums[1] = {MLX5_EVENT_TYPE_SRQ_LIMIT_REACHED};
	struct mlx5_rxq_data *rxq_data;
	uint32_t wqe_cnt;
	uint64_t cookie;
	int ret = 0;

	if (!rxq) {
		rte_errno = EINVAL;
		return -rte_errno;
	}
	rxq_data = &rxq->ctrl->rxq;
	/* Ensure the Rq is created by devx. */
	if (priv->obj_ops.rxq_obj_new != devx_obj_ops.rxq_obj_new) {
		rte_errno = EINVAL;
		return -rte_errno;
	}
	if (lwm > 99) {
		DRV_LOG(WARNING, "Too big LWM configuration.");
		rte_errno = E2BIG;
		return -rte_errno;
	}
	/* Start config LWM. */
	pthread_mutex_lock(&priv->sh->lwm_config_lock);
	if (rxq->lwm == 0 && lwm == 0) {
		/* Both old/new values are 0, do nothing. */
		ret = 0;
		goto end;
	}
	wqe_cnt = 1 << (rxq_data->elts_n - rxq_data->sges_n);
	if (lwm) {
		if (!priv->sh->devx_channel_lwm) {
			ret = mlx5_lwm_setup(priv);
			if (ret) {
				DRV_LOG(WARNING,
					"Failed to create shared_lwm.");
				rte_errno = ENOMEM;
				ret = -rte_errno;
				goto end;
			}
		}
		if (!rxq->lwm_devx_subscribed) {
			cookie = ((uint32_t)
				  (port_id << LWM_COOKIE_PORTID_OFFSET)) |
				(rx_queue_id << LWM_COOKIE_RXQID_OFFSET);
			ret = mlx5_os_devx_subscribe_devx_event
				(priv->sh->devx_channel_lwm,
				 rxq->devx_rq.rq->obj,
				 sizeof(event_nums),
				 event_nums,
				 cookie);
			if (ret) {
				rte_errno = rte_errno ? rte_errno : EINVAL;
				ret = -rte_errno;
				goto end;
			}
			rxq->lwm_devx_subscribed = 1;
		}
	}
	/* Save LWM to rxq and send modify_rq devx command. */
	rxq->lwm = lwm * wqe_cnt / 100;
	/* Prevent integer division loss when switch lwm number to percentage. */
	if (lwm && (lwm * wqe_cnt % 100)) {
		rxq->lwm = ((uint32_t)(rxq->lwm + 1) >= wqe_cnt) ?
			rxq->lwm : (rxq->lwm + 1);
	}
	if (lwm && !rxq->lwm) {
		/* With mprq, wqe_cnt may be < 100. */
		DRV_LOG(WARNING, "Too small LWM configuration.");
		rte_errno = EINVAL;
		ret = -rte_errno;
		goto end;
	}
	ret = mlx5_devx_modify_rq(rxq, MLX5_RXQ_MOD_RDY2RDY);
end:
	pthread_mutex_unlock(&priv->sh->lwm_config_lock);
	return ret;
}
mlx5_rx_queue_lwm_set(struct rte_eth_dev *dev, uint16_t rx_queue_id,
		      uint8_t lwm)
{
	struct mlx5_priv *priv = dev->data->dev_private;
	uint16_t port_id = PORT_ID(priv);
	struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, rx_queue_id);
	uint16_t event_nums[1] = {MLX5_EVENT_TYPE_SRQ_LIMIT_REACHED};
	struct mlx5_rxq_data *rxq_data;
	uint32_t wqe_cnt;
	uint64_t cookie;
	int ret = 0;

	if (!rxq) {
		rte_errno = EINVAL;
		return -rte_errno;
	}
	rxq_data = &rxq->ctrl->rxq;
	 
	if (priv->obj_ops.rxq_obj_new != devx_obj_ops.rxq_obj_new) {
		rte_errno = EINVAL;
		return -rte_errno;
	}
	if (lwm > 99) {
		DRV_LOG(WARNING, "Too big LWM configuration.");
		rte_errno = E2BIG;
		return -rte_errno;
	}
	 
	pthread_mutex_lock(&priv->sh->lwm_config_lock);
	if (rxq->lwm == 0 && lwm == 0) {
		 
		ret = 0;
		goto end;
	}
	wqe_cnt = 1 << (rxq_data->elts_n - rxq_data->sges_n);
	if (lwm) {
		if (!priv->sh->devx_channel_lwm) {
			ret = mlx5_lwm_setup(priv);
			if (ret) {
				DRV_LOG(WARNING,
					"Failed to create shared_lwm.");
				rte_errno = ENOMEM;
				ret = -rte_errno;
				goto end;
			}
		}
		if (!rxq->lwm_devx_subscribed) {
			cookie = ((uint32_t)
				  (port_id << LWM_COOKIE_PORTID_OFFSET)) |
				(rx_queue_id << LWM_COOKIE_RXQID_OFFSET);
			ret = mlx5_os_devx_subscribe_devx_event
				(priv->sh->devx_channel_lwm,
				 rxq->devx_rq.rq->obj,
				 sizeof(event_nums),
				 event_nums,
				 cookie);
			if (ret) {
				rte_errno = rte_errno ? rte_errno : EINVAL;
				ret = -rte_errno;
				goto end;
			}
			rxq->lwm_devx_subscribed = 1;
		}
	}
	 
	rxq->lwm = lwm * wqe_cnt / 100;
	 
	if (lwm && (lwm * wqe_cnt % 100)) {
		rxq->lwm = ((uint32_t)(rxq->lwm + 1) >= wqe_cnt) ?
			rxq->lwm : (rxq->lwm + 1);
	}
	if (lwm && !rxq->lwm) {
		 
		DRV_LOG(WARNING, "Too small LWM configuration.");
		rte_errno = EINVAL;
		ret = -rte_errno;
		goto end;
	}
	ret = mlx5_devx_modify_rq(rxq, MLX5_RXQ_MOD_RDY2RDY);
end:
	pthread_mutex_unlock(&priv->sh->lwm_config_lock);
	return ret;
}