Skip to content

Commit

Permalink
octeontx2-pf: Refactor schedular queue alloc/free calls
Browse files Browse the repository at this point in the history
[ Upstream commit 6b4b2de ]

1. Upon txschq free request, the transmit schedular config in hardware
is not getting reset. This patch adds necessary changes to do the same.

2. Current implementation calls txschq alloc during interface
initialization and in response handler updates the default txschq array.
This creates a problem for htb offload where txsch alloc will be called
for every tc class. This patch addresses the issue by reading txschq
response in mbox caller function instead in the response handler.

3. Current otx2_txschq_stop routine tries to free all txschq nodes
allocated to the interface. This creates a problem for htb offload.
This patch introduces the otx2_txschq_free_one to free txschq in a
given level.

Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: a9ac2e1 ("octeontx2-pf: Fix PFC TX scheduler free")
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Hariprasad Kelam authored and gregkh committed Sep 13, 2023
1 parent 23a7b87 commit 80de42d
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 38 deletions.
45 changes: 45 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
Expand Up @@ -1691,6 +1691,42 @@ handle_txschq_shaper_update(struct rvu *rvu, int blkaddr, int nixlf,
return true;
}

static void nix_reset_tx_schedule(struct rvu *rvu, int blkaddr,
int lvl, int schq)
{
u64 tlx_parent = 0, tlx_schedule = 0;

switch (lvl) {
case NIX_TXSCH_LVL_TL2:
tlx_parent = NIX_AF_TL2X_PARENT(schq);
tlx_schedule = NIX_AF_TL2X_SCHEDULE(schq);
break;
case NIX_TXSCH_LVL_TL3:
tlx_parent = NIX_AF_TL3X_PARENT(schq);
tlx_schedule = NIX_AF_TL3X_SCHEDULE(schq);
break;
case NIX_TXSCH_LVL_TL4:
tlx_parent = NIX_AF_TL4X_PARENT(schq);
tlx_schedule = NIX_AF_TL4X_SCHEDULE(schq);
break;
case NIX_TXSCH_LVL_MDQ:
/* no need to reset SMQ_CFG as HW clears this CSR
* on SMQ flush
*/
tlx_parent = NIX_AF_MDQX_PARENT(schq);
tlx_schedule = NIX_AF_MDQX_SCHEDULE(schq);
break;
default:
return;
}

if (tlx_parent)
rvu_write64(rvu, blkaddr, tlx_parent, 0x0);

if (tlx_schedule)
rvu_write64(rvu, blkaddr, tlx_schedule, 0x0);
}

/* Disable shaping of pkts by a scheduler queue
* at a given scheduler level.
*/
Expand Down Expand Up @@ -2040,6 +2076,7 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu,
pfvf_map[schq] = TXSCH_MAP(pcifunc, 0);
nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
}

for (idx = 0; idx < req->schq[lvl]; idx++) {
Expand All @@ -2049,6 +2086,7 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu,
pfvf_map[schq] = TXSCH_MAP(pcifunc, 0);
nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
}
}

Expand Down Expand Up @@ -2137,6 +2175,7 @@ static int nix_txschq_free(struct rvu *rvu, u16 pcifunc)
continue;
nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
nix_clear_tx_xoff(rvu, blkaddr, lvl, schq);
nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
}
}
nix_clear_tx_xoff(rvu, blkaddr, NIX_TXSCH_LVL_TL1,
Expand Down Expand Up @@ -2175,6 +2214,7 @@ static int nix_txschq_free(struct rvu *rvu, u16 pcifunc)
for (schq = 0; schq < txsch->schq.max; schq++) {
if (TXSCH_MAP_FUNC(txsch->pfvf_map[schq]) != pcifunc)
continue;
nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
rvu_free_rsrc(&txsch->schq, schq);
txsch->pfvf_map[schq] = TXSCH_MAP(0, NIX_TXSCHQ_FREE);
}
Expand Down Expand Up @@ -2234,6 +2274,9 @@ static int nix_txschq_free_one(struct rvu *rvu,
*/
nix_clear_tx_xoff(rvu, blkaddr, lvl, schq);

nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);

/* Flush if it is a SMQ. Onus of disabling
* TL2/3 queue links before SMQ flush is on user
*/
Expand All @@ -2243,6 +2286,8 @@ static int nix_txschq_free_one(struct rvu *rvu,
goto err;
}

nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);

/* Free the resource */
rvu_free_rsrc(&txsch->schq, schq);
txsch->pfvf_map[schq] = TXSCH_MAP(0, NIX_TXSCHQ_FREE);
Expand Down
67 changes: 44 additions & 23 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
Expand Up @@ -716,7 +716,8 @@ EXPORT_SYMBOL(otx2_smq_flush);
int otx2_txsch_alloc(struct otx2_nic *pfvf)
{
struct nix_txsch_alloc_req *req;
int lvl;
struct nix_txsch_alloc_rsp *rsp;
int lvl, schq, rc;

/* Get memory to put this msg */
req = otx2_mbox_alloc_msg_nix_txsch_alloc(&pfvf->mbox);
Expand All @@ -726,33 +727,68 @@ int otx2_txsch_alloc(struct otx2_nic *pfvf)
/* Request one schq per level */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
req->schq[lvl] = 1;
rc = otx2_sync_mbox_msg(&pfvf->mbox);
if (rc)
return rc;

return otx2_sync_mbox_msg(&pfvf->mbox);
rsp = (struct nix_txsch_alloc_rsp *)
otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
if (IS_ERR(rsp))
return PTR_ERR(rsp);

/* Setup transmit scheduler list */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
for (schq = 0; schq < rsp->schq[lvl]; schq++)
pfvf->hw.txschq_list[lvl][schq] =
rsp->schq_list[lvl][schq];

pfvf->hw.txschq_link_cfg_lvl = rsp->link_cfg_lvl;

return 0;
}

int otx2_txschq_stop(struct otx2_nic *pfvf)
void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq)
{
struct nix_txsch_free_req *free_req;
int lvl, schq, err;
int err;

mutex_lock(&pfvf->mbox.lock);
/* Free the transmit schedulers */

free_req = otx2_mbox_alloc_msg_nix_txsch_free(&pfvf->mbox);
if (!free_req) {
mutex_unlock(&pfvf->mbox.lock);
return -ENOMEM;
netdev_err(pfvf->netdev,
"Failed alloc txschq free req\n");
return;
}

free_req->flags = TXSCHQ_FREE_ALL;
free_req->schq_lvl = lvl;
free_req->schq = schq;

err = otx2_sync_mbox_msg(&pfvf->mbox);
if (err) {
netdev_err(pfvf->netdev,
"Failed stop txschq %d at level %d\n", schq, lvl);
}

mutex_unlock(&pfvf->mbox.lock);
}

void otx2_txschq_stop(struct otx2_nic *pfvf)
{
int lvl, schq;

/* free non QOS TLx nodes */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
otx2_txschq_free_one(pfvf, lvl,
pfvf->hw.txschq_list[lvl][0]);

/* Clear the txschq list */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
for (schq = 0; schq < MAX_TXSCHQ_PER_FUNC; schq++)
pfvf->hw.txschq_list[lvl][schq] = 0;
}
return err;

}

void otx2_sqb_flush(struct otx2_nic *pfvf)
Expand Down Expand Up @@ -1629,21 +1665,6 @@ void mbox_handler_cgx_fec_stats(struct otx2_nic *pfvf,
pfvf->hw.cgx_fec_uncorr_blks += rsp->fec_uncorr_blks;
}

void mbox_handler_nix_txsch_alloc(struct otx2_nic *pf,
struct nix_txsch_alloc_rsp *rsp)
{
int lvl, schq;

/* Setup transmit scheduler list */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
for (schq = 0; schq < rsp->schq[lvl]; schq++)
pf->hw.txschq_list[lvl][schq] =
rsp->schq_list[lvl][schq];

pf->hw.txschq_link_cfg_lvl = rsp->link_cfg_lvl;
}
EXPORT_SYMBOL(mbox_handler_nix_txsch_alloc);

void mbox_handler_npa_lf_alloc(struct otx2_nic *pfvf,
struct npa_lf_alloc_rsp *rsp)
{
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
Expand Up @@ -917,7 +917,8 @@ int otx2_config_nix(struct otx2_nic *pfvf);
int otx2_config_nix_queues(struct otx2_nic *pfvf);
int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool pfc_en);
int otx2_txsch_alloc(struct otx2_nic *pfvf);
int otx2_txschq_stop(struct otx2_nic *pfvf);
void otx2_txschq_stop(struct otx2_nic *pfvf);
void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq);
void otx2_sqb_flush(struct otx2_nic *pfvf);
int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
dma_addr_t *dma);
Expand Down
13 changes: 3 additions & 10 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
Expand Up @@ -791,10 +791,6 @@ static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf,
case MBOX_MSG_NIX_LF_ALLOC:
mbox_handler_nix_lf_alloc(pf, (struct nix_lf_alloc_rsp *)msg);
break;
case MBOX_MSG_NIX_TXSCH_ALLOC:
mbox_handler_nix_txsch_alloc(pf,
(struct nix_txsch_alloc_rsp *)msg);
break;
case MBOX_MSG_NIX_BP_ENABLE:
mbox_handler_nix_bp_enable(pf, (struct nix_bp_cfg_rsp *)msg);
break;
Expand Down Expand Up @@ -1517,8 +1513,7 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
otx2_free_cq_res(pf);
otx2_ctx_disable(mbox, NIX_AQ_CTYPE_RQ, false);
err_free_txsch:
if (otx2_txschq_stop(pf))
dev_err(pf->dev, "%s failed to stop TX schedulers\n", __func__);
otx2_txschq_stop(pf);
err_free_sq_ptrs:
otx2_sq_free_sqbs(pf);
err_free_rq_ptrs:
Expand Down Expand Up @@ -1553,15 +1548,13 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
struct mbox *mbox = &pf->mbox;
struct otx2_cq_queue *cq;
struct msg_req *req;
int qidx, err;
int qidx;

/* Ensure all SQE are processed */
otx2_sqb_flush(pf);

/* Stop transmission */
err = otx2_txschq_stop(pf);
if (err)
dev_err(pf->dev, "RVUPF: Failed to stop/free TX schedulers\n");
otx2_txschq_stop(pf);

#ifdef CONFIG_DCB
if (pf->pfc_en)
Expand Down
4 changes: 0 additions & 4 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
Expand Up @@ -70,10 +70,6 @@ static void otx2vf_process_vfaf_mbox_msg(struct otx2_nic *vf,
case MBOX_MSG_NIX_LF_ALLOC:
mbox_handler_nix_lf_alloc(vf, (struct nix_lf_alloc_rsp *)msg);
break;
case MBOX_MSG_NIX_TXSCH_ALLOC:
mbox_handler_nix_txsch_alloc(vf,
(struct nix_txsch_alloc_rsp *)msg);
break;
case MBOX_MSG_NIX_BP_ENABLE:
mbox_handler_nix_bp_enable(vf, (struct nix_bp_cfg_rsp *)msg);
break;
Expand Down

0 comments on commit 80de42d

Please sign in to comment.