From: Satha Rao <skoteshwar@marvell.com>
Host SDP port closes the SDP link on NIX causes crash when
BP enabled on SDP link. This patch disables BP on SDP link
when SQ flush fails due to link disabled at host.
Signed-off-by: Satha Rao <skoteshwar@marvell.com>
---
drivers/common/cnxk/roc_nix_tm.c | 73 ++++++++++++++++++++++++++++++--
1 file changed, 70 insertions(+), 3 deletions(-)
@@ -610,8 +610,6 @@ roc_nix_tm_sq_flush_spin(struct roc_nix_sq *sq)
return 0;
exit:
- roc_nix_tm_dump(sq->roc_nix, NULL);
- roc_nix_queues_ctx_dump(sq->roc_nix, NULL);
return -EFAULT;
}
@@ -748,6 +746,70 @@ roc_nix_tm_sq_free_pending_sqe(struct nix *nix, int q)
return 0;
}
+static inline int
+nix_tm_sdp_sq_drop_pkts(struct roc_nix *roc_nix, struct roc_nix_sq *sq)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct mbox *mbox = mbox_get((&nix->dev)->mbox);
+ struct nix_txschq_config *req = NULL, *rsp;
+ enum roc_nix_tm_tree tree = nix->tm_tree;
+ int rc = 0, qid = sq->qid;
+ struct nix_tm_node *node;
+ uint64_t regval;
+
+ /* Find the node for this SQ */
+ node = nix_tm_node_search(nix, qid, tree);
+ while (node) {
+ if (node->hw_lvl != NIX_TXSCH_LVL_TL4) {
+ node = node->parent;
+ continue;
+ }
+ break;
+ }
+ if (!node) {
+ plt_err("Invalid node/state for sq %u", qid);
+ return -EFAULT;
+ }
+
+ /* Get present link config */
+ req = mbox_alloc_msg_nix_txschq_cfg(mbox);
+ req->read = 1;
+ req->lvl = NIX_TXSCH_LVL_TL4;
+ req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id);
+ req->num_regs = 1;
+ rc = mbox_process_msg(mbox, (void **)&rsp);
+ if (rc || rsp->num_regs != 1)
+ goto err;
+ regval = rsp->regval[0];
+ /* Disable BP_ENA in SDP link config */
+ req = mbox_alloc_msg_nix_txschq_cfg(mbox);
+ req->lvl = NIX_TXSCH_LVL_TL4;
+ req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id);
+ req->regval[0] = 0x0ull;
+ req->regval_mask[0] = ~(BIT_ULL(13));
+ req->num_regs = 1;
+ rc = mbox_process(mbox);
+ if (rc)
+ goto err;
+ mbox_put(mbox);
+ /* Flush SQ to drop all packets */
+ rc = roc_nix_tm_sq_flush_spin(sq);
+ if (rc)
+ plt_nix_dbg("SQ flush failed with link reset config rc %d", rc);
+ mbox = mbox_get((&nix->dev)->mbox);
+ /* Restore link config */
+ req = mbox_alloc_msg_nix_txschq_cfg(mbox);
+ req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id);
+ req->lvl = NIX_TXSCH_LVL_TL4;
+ req->regval[0] = regval;
+ req->regval_mask[0] = ~(BIT_ULL(13) | BIT_ULL(12) | GENMASK_ULL(7, 0));
+ req->num_regs = 1;
+ rc = mbox_process(mbox);
+err:
+ mbox_put(mbox);
+ return rc;
+}
+
/* Flush and disable tx queue and its parent SMQ */
int
nix_tm_sq_flush_pre(struct roc_nix_sq *sq)
@@ -834,8 +896,13 @@ nix_tm_sq_flush_pre(struct roc_nix_sq *sq)
/* Wait for sq entries to be flushed */
rc = roc_nix_tm_sq_flush_spin(sq);
if (rc) {
- rc = roc_nix_tm_sq_free_pending_sqe(nix, sq->qid);
+ if (nix->sdp_link)
+ rc = nix_tm_sdp_sq_drop_pkts(roc_nix, sq);
+ else
+ rc = roc_nix_tm_sq_free_pending_sqe(nix, sq->qid);
if (rc) {
+ roc_nix_tm_dump(sq->roc_nix, NULL);
+ roc_nix_queues_ctx_dump(sq->roc_nix, NULL);
plt_err("Failed to drain sq %u, rc=%d\n", sq->qid, rc);
return rc;
}