@@ -2259,14 +2259,13 @@ static void nix_smq_flush_fill_ctx(struct rvu *rvu, int blkaddr, int smq,
2259
2259
schq = smq ;
2260
2260
for (lvl = NIX_TXSCH_LVL_SMQ ; lvl <= NIX_TXSCH_LVL_TL1 ; lvl ++ ) {
2261
2261
smq_tree_ctx = & smq_flush_ctx -> smq_tree_ctx [lvl ];
2262
+ smq_tree_ctx -> schq = schq ;
2262
2263
if (lvl == NIX_TXSCH_LVL_TL1 ) {
2263
- smq_flush_ctx -> tl1_schq = schq ;
2264
2264
smq_tree_ctx -> cir_off = NIX_AF_TL1X_CIR (schq );
2265
2265
smq_tree_ctx -> pir_off = 0 ;
2266
2266
smq_tree_ctx -> pir_val = 0 ;
2267
2267
parent_off = 0 ;
2268
2268
} else if (lvl == NIX_TXSCH_LVL_TL2 ) {
2269
- smq_flush_ctx -> tl2_schq = schq ;
2270
2269
smq_tree_ctx -> cir_off = NIX_AF_TL2X_CIR (schq );
2271
2270
smq_tree_ctx -> pir_off = NIX_AF_TL2X_PIR (schq );
2272
2271
parent_off = NIX_AF_TL2X_PARENT (schq );
@@ -2301,25 +2300,26 @@ static void nix_smq_flush_enadis_xoff(struct rvu *rvu, int blkaddr,
2301
2300
{
2302
2301
struct nix_txsch * txsch ;
2303
2302
struct nix_hw * nix_hw ;
2303
+ int tl2 , tl2_schq ;
2304
2304
u64 regoff ;
2305
- int tl2 ;
2306
2305
2307
2306
nix_hw = get_nix_hw (rvu -> hw , blkaddr );
2308
2307
if (!nix_hw )
2309
2308
return ;
2310
2309
2311
2310
/* loop through all TL2s with matching PF_FUNC */
2312
2311
txsch = & nix_hw -> txsch [NIX_TXSCH_LVL_TL2 ];
2312
+ tl2_schq = smq_flush_ctx -> smq_tree_ctx [NIX_TXSCH_LVL_TL2 ].schq ;
2313
2313
for (tl2 = 0 ; tl2 < txsch -> schq .max ; tl2 ++ ) {
2314
2314
/* skip the smq(flush) TL2 */
2315
- if (tl2 == smq_flush_ctx -> tl2_schq )
2315
+ if (tl2 == tl2_schq )
2316
2316
continue ;
2317
2317
/* skip unused TL2s */
2318
2318
if (TXSCH_MAP_FLAGS (txsch -> pfvf_map [tl2 ]) & NIX_TXSCHQ_FREE )
2319
2319
continue ;
2320
2320
/* skip if PF_FUNC doesn't match */
2321
2321
if ((TXSCH_MAP_FUNC (txsch -> pfvf_map [tl2 ]) & ~RVU_PFVF_FUNC_MASK ) !=
2322
- (TXSCH_MAP_FUNC (txsch -> pfvf_map [smq_flush_ctx -> tl2_schq ] &
2322
+ (TXSCH_MAP_FUNC (txsch -> pfvf_map [tl2_schq ] &
2323
2323
~RVU_PFVF_FUNC_MASK )))
2324
2324
continue ;
2325
2325
/* enable/disable XOFF */
@@ -2361,10 +2361,12 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
2361
2361
int smq , u16 pcifunc , int nixlf )
2362
2362
{
2363
2363
struct nix_smq_flush_ctx * smq_flush_ctx ;
2364
+ int err , restore_tx_en = 0 , i ;
2364
2365
int pf = rvu_get_pf (pcifunc );
2365
2366
u8 cgx_id = 0 , lmac_id = 0 ;
2366
- int err , restore_tx_en = 0 ;
2367
- u64 cfg ;
2367
+ u16 tl2_tl3_link_schq ;
2368
+ u8 link , link_level ;
2369
+ u64 cfg , bmap = 0 ;
2368
2370
2369
2371
if (!is_rvu_otx2 (rvu )) {
2370
2372
/* Skip SMQ flush if pkt count is zero */
@@ -2388,16 +2390,38 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
2388
2390
nix_smq_flush_enadis_xoff (rvu , blkaddr , smq_flush_ctx , true);
2389
2391
nix_smq_flush_enadis_rate (rvu , blkaddr , smq_flush_ctx , false);
2390
2392
2391
- cfg = rvu_read64 (rvu , blkaddr , NIX_AF_SMQX_CFG (smq ));
2392
- /* Do SMQ flush and set enqueue xoff */
2393
- cfg |= BIT_ULL (50 ) | BIT_ULL (49 );
2394
- rvu_write64 (rvu , blkaddr , NIX_AF_SMQX_CFG (smq ), cfg );
2395
-
2396
2393
/* Disable backpressure from physical link,
2397
2394
* otherwise SMQ flush may stall.
2398
2395
*/
2399
2396
rvu_cgx_enadis_rx_bp (rvu , pf , false);
2400
2397
2398
+ link_level = rvu_read64 (rvu , blkaddr , NIX_AF_PSE_CHANNEL_LEVEL ) & 0x01 ?
2399
+ NIX_TXSCH_LVL_TL3 : NIX_TXSCH_LVL_TL2 ;
2400
+ tl2_tl3_link_schq = smq_flush_ctx -> smq_tree_ctx [link_level ].schq ;
2401
+ link = smq_flush_ctx -> smq_tree_ctx [NIX_TXSCH_LVL_TL1 ].schq ;
2402
+
2403
+ /* SMQ set enqueue xoff */
2404
+ cfg = rvu_read64 (rvu , blkaddr , NIX_AF_SMQX_CFG (smq ));
2405
+ cfg |= BIT_ULL (50 );
2406
+ rvu_write64 (rvu , blkaddr , NIX_AF_SMQX_CFG (smq ), cfg );
2407
+
2408
+ /* Clear all NIX_AF_TL3_TL2_LINK_CFG[ENA] for the TL3/TL2 queue */
2409
+ for (i = 0 ; i < (rvu -> hw -> cgx_links + rvu -> hw -> lbk_links ); i ++ ) {
2410
+ cfg = rvu_read64 (rvu , blkaddr ,
2411
+ NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq , link ));
2412
+ if (!(cfg & BIT_ULL (12 )))
2413
+ continue ;
2414
+ bmap |= (1 << i );
2415
+ cfg &= ~BIT_ULL (12 );
2416
+ rvu_write64 (rvu , blkaddr ,
2417
+ NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq , link ), cfg );
2418
+ }
2419
+
2420
+ /* Do SMQ flush and set enqueue xoff */
2421
+ cfg = rvu_read64 (rvu , blkaddr , NIX_AF_SMQX_CFG (smq ));
2422
+ cfg |= BIT_ULL (50 ) | BIT_ULL (49 );
2423
+ rvu_write64 (rvu , blkaddr , NIX_AF_SMQX_CFG (smq ), cfg );
2424
+
2401
2425
/* Wait for flush to complete */
2402
2426
err = rvu_poll_reg (rvu , blkaddr ,
2403
2427
NIX_AF_SMQX_CFG (smq ), BIT_ULL (49 ), true);
@@ -2406,6 +2430,17 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
2406
2430
"NIXLF%d: SMQ%d flush failed, txlink might be busy\n" ,
2407
2431
nixlf , smq );
2408
2432
2433
+ /* Set NIX_AF_TL3_TL2_LINKX_CFG[ENA] for the TL3/TL2 queue */
2434
+ for (i = 0 ; i < (rvu -> hw -> cgx_links + rvu -> hw -> lbk_links ); i ++ ) {
2435
+ if (!(bmap & (1 << i )))
2436
+ continue ;
2437
+ cfg = rvu_read64 (rvu , blkaddr ,
2438
+ NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq , link ));
2439
+ cfg |= BIT_ULL (12 );
2440
+ rvu_write64 (rvu , blkaddr ,
2441
+ NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq , link ), cfg );
2442
+ }
2443
+
2409
2444
/* clear XOFF on TL2s */
2410
2445
nix_smq_flush_enadis_rate (rvu , blkaddr , smq_flush_ctx , true);
2411
2446
nix_smq_flush_enadis_xoff (rvu , blkaddr , smq_flush_ctx , false);
0 commit comments