summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatan Azrad <matan@mellanox.com>2019-05-30 10:20:39 +0000
committerFerruh Yigit <ferruh.yigit@intel.com>2019-06-14 00:01:06 +0900
commit35c090eac1c6fcb2f2a80c274b519fbb304686d3 (patch)
tree9fcf5ffea1a1379b82382879afc9e9b5e8837e53
parent2d77cb615b2c126828c4e98b686523bf0139c1c1 (diff)
downloaddpdk-35c090eac1c6fcb2f2a80c274b519fbb304686d3.zip
dpdk-35c090eac1c6fcb2f2a80c274b519fbb304686d3.tar.gz
dpdk-35c090eac1c6fcb2f2a80c274b519fbb304686d3.tar.xz
net/mlx5: recover secondary process Tx errors
The SQ errors recovery mechanism in the PMD invokes a Verbs functions to modify the RQ states in order to reset the SQ and to reactivate it. These Verbs functions are not allowed to be invoked from a secondary process, hence the PMD skips the recovery when the error is captured by secondary processes queues. Using the DPDK IPC mechanism the secondary process can request Verbs queues state modifications to be done synchronically by the primary process. Add support for secondary process Tx errors recovery. Cc: stable@dpdk.org Signed-off-by: Matan Azrad <matan@mellanox.com> Acked-by: Shahaf Shuler <shahafs@mellanox.com>
-rw-r--r--drivers/net/mlx5/mlx5_rxtx.c104
1 files changed, 62 insertions, 42 deletions
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 3857c16..c1dc8c4 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -51,6 +51,10 @@ rxq_cq_to_mbuf(struct mlx5_rxq_data *rxq, struct rte_mbuf *pkt,
static __rte_always_inline void
mprq_buf_replace(struct mlx5_rxq_data *rxq, uint16_t rq_idx);
+static int
+mlx5_queue_state_modify(struct rte_eth_dev *dev,
+ struct mlx5_mp_arg_queue_state_modify *sm);
+
uint32_t mlx5_ptype_table[] __rte_cache_aligned = {
[0xff] = RTE_PTYPE_ALL_MASK, /* Last entry for errored packet. */
};
@@ -570,52 +574,27 @@ mlx5_dump_debug_information(const char *fname, const char *hex_title,
}
/**
- * Move QP from error state to running state.
+ * Move QP from error state to running state and initialize indexes.
*
- * @param txq
- * Pointer to TX queue structure.
- * @param qp
- * The qp pointer for recovery.
+ * @param txq_ctrl
+ * Pointer to TX queue control structure.
*
* @return
- * 0 on success, else errno value.
+ * 0 on success, else -1.
*/
static int
-tx_recover_qp(struct mlx5_txq_data *txq, struct ibv_qp *qp)
+tx_recover_qp(struct mlx5_txq_ctrl *txq_ctrl)
{
- int ret;
- struct ibv_qp_attr mod = {
- .qp_state = IBV_QPS_RESET,
- .port_num = 1,
- };
- ret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);
- if (ret) {
- DRV_LOG(ERR, "Cannot change the Tx QP state to RESET %d\n",
- ret);
- return ret;
- }
- mod.qp_state = IBV_QPS_INIT;
- ret = mlx5_glue->modify_qp(qp, &mod,
- (IBV_QP_STATE | IBV_QP_PORT));
- if (ret) {
- DRV_LOG(ERR, "Cannot change Tx QP state to INIT %d\n", ret);
- return ret;
- }
- mod.qp_state = IBV_QPS_RTR;
- ret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);
- if (ret) {
- DRV_LOG(ERR, "Cannot change Tx QP state to RTR %d\n", ret);
- return ret;
- }
- mod.qp_state = IBV_QPS_RTS;
- ret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);
- if (ret) {
- DRV_LOG(ERR, "Cannot change Tx QP state to RTS %d\n", ret);
- return ret;
- }
- txq->wqe_ci = 0;
- txq->wqe_pi = 0;
- txq->elts_comp = 0;
+ struct mlx5_mp_arg_queue_state_modify sm = {
+ .is_wq = 0,
+ .queue_id = txq_ctrl->txq.idx,
+ };
+
+ if (mlx5_queue_state_modify(ETH_DEV(txq_ctrl->priv), &sm))
+ return -1;
+ txq_ctrl->txq.wqe_ci = 0;
+ txq_ctrl->txq.wqe_pi = 0;
+ txq_ctrl->txq.elts_comp = 0;
return 0;
}
@@ -690,8 +669,7 @@ mlx5_tx_error_cqe_handle(struct mlx5_txq_data *txq,
*/
txq->stats.oerrors += ((txq->wqe_ci & wqe_m) -
new_wqe_pi) & wqe_m;
- if ((rte_eal_process_type() == RTE_PROC_PRIMARY) &&
- tx_recover_qp(txq, txq_ctrl->ibv->qp) == 0) {
+ if (tx_recover_qp(txq_ctrl) == 0) {
txq->cq_ci++;
/* Release all the remaining buffers. */
return txq->elts_head;
@@ -2065,6 +2043,48 @@ mlx5_queue_state_modify_primary(struct rte_eth_dev *dev,
rte_errno = errno;
return ret;
}
+ } else {
+ struct mlx5_txq_data *txq = (*priv->txqs)[sm->queue_id];
+ struct mlx5_txq_ctrl *txq_ctrl =
+ container_of(txq, struct mlx5_txq_ctrl, txq);
+ struct ibv_qp_attr mod = {
+ .qp_state = IBV_QPS_RESET,
+ .port_num = (uint8_t)priv->ibv_port,
+ };
+ struct ibv_qp *qp = txq_ctrl->ibv->qp;
+
+ ret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);
+ if (ret) {
+ DRV_LOG(ERR, "Cannot change the Tx QP state to RESET "
+ "%s\n", strerror(errno));
+ rte_errno = errno;
+ return ret;
+ }
+ mod.qp_state = IBV_QPS_INIT;
+ ret = mlx5_glue->modify_qp(qp, &mod,
+ (IBV_QP_STATE | IBV_QP_PORT));
+ if (ret) {
+ DRV_LOG(ERR, "Cannot change Tx QP state to INIT %s\n",
+ strerror(errno));
+ rte_errno = errno;
+ return ret;
+ }
+ mod.qp_state = IBV_QPS_RTR;
+ ret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);
+ if (ret) {
+ DRV_LOG(ERR, "Cannot change Tx QP state to RTR %s\n",
+ strerror(errno));
+ rte_errno = errno;
+ return ret;
+ }
+ mod.qp_state = IBV_QPS_RTS;
+ ret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);
+ if (ret) {
+ DRV_LOG(ERR, "Cannot change Tx QP state to RTS %s\n",
+ strerror(errno));
+ rte_errno = errno;
+ return ret;
+ }
}
return 0;
}