Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'octeon-drr-config'

Sunil Goutham says:

====================
cn10k: DWRR MTU and weights configuration

On OcteonTx2 DWRR quantum is directly configured into each of
the transmit scheduler queues. And PF/VF drivers were free to
config any value upto 2^24.

On CN10K, HW is modified, the quantum configuration at scheduler
queues is in terms of weight. And SW needs to setup a base DWRR MTU
at NIX_AF_DWRR_RPM_MTU / NIX_AF_DWRR_SDP_MTU. HW will do
'DWRR MTU * weight' to get the quantum.

This patch series addresses this HW change on CN10K silicons,
both admin function and PF/VF drivers are modified.

Also added support to program DWRR MTU via devlink params.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+253 -15
+1 -4
drivers/net/ethernet/marvell/octeontx2/af/common.h
··· 146 146 #define TXSCH_RR_QTM_MAX ((1 << 24) - 1) 147 147 #define TXSCH_TL1_DFLT_RR_QTM TXSCH_RR_QTM_MAX 148 148 #define TXSCH_TL1_DFLT_RR_PRIO (0x1ull) 149 - #define MAX_SCHED_WEIGHT 0xFF 150 - #define DFLT_RR_WEIGHT 71 151 - #define DFLT_RR_QTM ((DFLT_RR_WEIGHT * TXSCH_RR_QTM_MAX) \ 152 - / MAX_SCHED_WEIGHT) 149 + #define CN10K_MAX_DWRR_WEIGHT 16384 /* Weight is 14bit on CN10K */ 153 150 154 151 /* Min/Max packet sizes, excluding FCS */ 155 152 #define NIC_HW_MIN_FRS 40
+4
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
··· 1032 1032 1033 1033 struct nix_hw_info { 1034 1034 struct mbox_msghdr hdr; 1035 + u16 rsvs16; 1035 1036 u16 max_mtu; 1036 1037 u16 min_mtu; 1038 + u32 rpm_dwrr_mtu; 1039 + u32 sdp_dwrr_mtu; 1040 + u64 rsvd[16]; /* Add reserved fields for future expansion */ 1037 1041 }; 1038 1042 1039 1043 struct nix_bandprof_alloc_req {
+3
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
··· 329 329 bool nix_shaping; /* Is shaping and coloring supported */ 330 330 bool nix_tx_link_bp; /* Can link backpressure TL queues ? */ 331 331 bool nix_rx_multicast; /* Rx packet replication support */ 332 + bool nix_common_dwrr_mtu; /* Common DWRR MTU for quantum config */ 332 333 bool per_pf_mbox_regs; /* PF mbox specified in per PF registers ? */ 333 334 bool programmable_chans; /* Channels programmable ? */ 334 335 bool ipolicer; ··· 707 706 struct nix_cn10k_aq_enq_rsp *aq_rsp, 708 707 u16 pcifunc, u8 ctype, u32 qidx); 709 708 int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc); 709 + u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu); 710 + u32 convert_bytes_to_dwrr_mtu(u32 bytes); 710 711 711 712 /* NPC APIs */ 712 713 int rvu_npc_init(struct rvu *rvu);
+109 -1
drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
··· 1364 1364 rvu_nix_health_reporters_destroy(rvu_dl); 1365 1365 } 1366 1366 1367 + /* Devlink Params APIs */ 1368 + static int rvu_af_dl_dwrr_mtu_validate(struct devlink *devlink, u32 id, 1369 + union devlink_param_value val, 1370 + struct netlink_ext_ack *extack) 1371 + { 1372 + struct rvu_devlink *rvu_dl = devlink_priv(devlink); 1373 + struct rvu *rvu = rvu_dl->rvu; 1374 + int dwrr_mtu = val.vu32; 1375 + struct nix_txsch *txsch; 1376 + struct nix_hw *nix_hw; 1377 + 1378 + if (!rvu->hw->cap.nix_common_dwrr_mtu) { 1379 + NL_SET_ERR_MSG_MOD(extack, 1380 + "Setting DWRR_MTU is not supported on this silicon"); 1381 + return -EOPNOTSUPP; 1382 + } 1383 + 1384 + if ((dwrr_mtu > 65536 || !is_power_of_2(dwrr_mtu)) && 1385 + (dwrr_mtu != 9728 && dwrr_mtu != 10240)) { 1386 + NL_SET_ERR_MSG_MOD(extack, 1387 + "Invalid, supported MTUs are 0,2,4,8.16,32,64....4K,8K,32K,64K and 9728, 10240"); 1388 + return -EINVAL; 1389 + } 1390 + 1391 + nix_hw = get_nix_hw(rvu->hw, BLKADDR_NIX0); 1392 + if (!nix_hw) 1393 + return -ENODEV; 1394 + 1395 + txsch = &nix_hw->txsch[NIX_TXSCH_LVL_SMQ]; 1396 + if (rvu_rsrc_free_count(&txsch->schq) != txsch->schq.max) { 1397 + NL_SET_ERR_MSG_MOD(extack, 1398 + "Changing DWRR MTU is not supported when there are active NIXLFs"); 1399 + NL_SET_ERR_MSG_MOD(extack, 1400 + "Makesure none of the PF/VF interfaces are initialized and retry"); 1401 + return -EOPNOTSUPP; 1402 + } 1403 + 1404 + return 0; 1405 + } 1406 + 1407 + static int rvu_af_dl_dwrr_mtu_set(struct devlink *devlink, u32 id, 1408 + struct devlink_param_gset_ctx *ctx) 1409 + { 1410 + struct rvu_devlink *rvu_dl = devlink_priv(devlink); 1411 + struct rvu *rvu = rvu_dl->rvu; 1412 + u64 dwrr_mtu; 1413 + 1414 + dwrr_mtu = convert_bytes_to_dwrr_mtu(ctx->val.vu32); 1415 + rvu_write64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU, dwrr_mtu); 1416 + 1417 + return 0; 1418 + } 1419 + 1420 + static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id, 1421 + struct devlink_param_gset_ctx *ctx) 1422 + { 1423 + struct rvu_devlink *rvu_dl = devlink_priv(devlink); 1424 + struct rvu *rvu = rvu_dl->rvu; 1425 + u64 dwrr_mtu; 1426 + 1427 + if (!rvu->hw->cap.nix_common_dwrr_mtu) 1428 + return -EOPNOTSUPP; 1429 + 1430 + dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU); 1431 + ctx->val.vu32 = convert_dwrr_mtu_to_bytes(dwrr_mtu); 1432 + 1433 + return 0; 1434 + } 1435 + 1436 + enum rvu_af_dl_param_id { 1437 + RVU_AF_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 1438 + RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU, 1439 + }; 1440 + 1441 + static const struct devlink_param rvu_af_dl_params[] = { 1442 + DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU, 1443 + "dwrr_mtu", DEVLINK_PARAM_TYPE_U32, 1444 + BIT(DEVLINK_PARAM_CMODE_RUNTIME), 1445 + rvu_af_dl_dwrr_mtu_get, rvu_af_dl_dwrr_mtu_set, 1446 + rvu_af_dl_dwrr_mtu_validate), 1447 + }; 1448 + 1449 + /* Devlink switch mode */ 1367 1450 static int rvu_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode) 1368 1451 { 1369 1452 struct rvu_devlink *rvu_dl = devlink_priv(devlink); ··· 1521 1438 rvu_dl->rvu = rvu; 1522 1439 rvu->rvu_dl = rvu_dl; 1523 1440 1524 - return rvu_health_reporters_create(rvu); 1441 + err = rvu_health_reporters_create(rvu); 1442 + if (err) { 1443 + dev_err(rvu->dev, 1444 + "devlink health reporter creation failed with error %d\n", err); 1445 + goto err_dl_health; 1446 + } 1447 + 1448 + err = devlink_params_register(dl, rvu_af_dl_params, 1449 + ARRAY_SIZE(rvu_af_dl_params)); 1450 + if (err) { 1451 + dev_err(rvu->dev, 1452 + "devlink params register failed with error %d", err); 1453 + goto err_dl_health; 1454 + } 1455 + 1456 + devlink_params_publish(dl); 1457 + 1458 + return 0; 1459 + 1460 + err_dl_health: 1461 + rvu_health_reporters_destroy(rvu); 1462 + devlink_unregister(dl); 1463 + devlink_free(dl); 1464 + return err; 1525 1465 } 1526 1466 1527 1467 void rvu_unregister_dl(struct rvu *rvu) ··· 1555 1449 if (!dl) 1556 1450 return; 1557 1451 1452 + devlink_params_unregister(dl, rvu_af_dl_params, 1453 + ARRAY_SIZE(rvu_af_dl_params)); 1558 1454 rvu_health_reporters_destroy(rvu); 1559 1455 devlink_unregister(dl); 1560 1456 devlink_free(dl);
+101 -2
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
··· 192 192 return NULL; 193 193 } 194 194 195 + u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu) 196 + { 197 + dwrr_mtu &= 0x1FULL; 198 + 199 + /* MTU used for DWRR calculation is in power of 2 up until 64K bytes. 200 + * Value of 4 is reserved for MTU value of 9728 bytes. 201 + * Value of 5 is reserved for MTU value of 10240 bytes. 202 + */ 203 + switch (dwrr_mtu) { 204 + case 4: 205 + return 9728; 206 + case 5: 207 + return 10240; 208 + default: 209 + return BIT_ULL(dwrr_mtu); 210 + } 211 + 212 + return 0; 213 + } 214 + 215 + u32 convert_bytes_to_dwrr_mtu(u32 bytes) 216 + { 217 + /* MTU used for DWRR calculation is in power of 2 up until 64K bytes. 218 + * Value of 4 is reserved for MTU value of 9728 bytes. 219 + * Value of 5 is reserved for MTU value of 10240 bytes. 220 + */ 221 + if (bytes > BIT_ULL(16)) 222 + return 0; 223 + 224 + switch (bytes) { 225 + case 9728: 226 + return 4; 227 + case 10240: 228 + return 5; 229 + default: 230 + return ilog2(bytes); 231 + } 232 + 233 + return 0; 234 + } 235 + 195 236 static void nix_rx_sync(struct rvu *rvu, int blkaddr) 196 237 { 197 238 int err; ··· 1999 1958 return; 2000 1959 rvu_write64(rvu, blkaddr, NIX_AF_TL1X_TOPOLOGY(schq), 2001 1960 (TXSCH_TL1_DFLT_RR_PRIO << 1)); 2002 - rvu_write64(rvu, blkaddr, NIX_AF_TL1X_SCHEDULE(schq), 2003 - TXSCH_TL1_DFLT_RR_QTM); 1961 + 1962 + /* On OcteonTx2 the config was in bytes and newer silcons 1963 + * it's changed to weight. 1964 + */ 1965 + if (!rvu->hw->cap.nix_common_dwrr_mtu) 1966 + rvu_write64(rvu, blkaddr, NIX_AF_TL1X_SCHEDULE(schq), 1967 + TXSCH_TL1_DFLT_RR_QTM); 1968 + else 1969 + rvu_write64(rvu, blkaddr, NIX_AF_TL1X_SCHEDULE(schq), 1970 + CN10K_MAX_DWRR_WEIGHT); 1971 + 2004 1972 rvu_write64(rvu, blkaddr, NIX_AF_TL1X_CIR(schq), 0x00); 2005 1973 pfvf_map[schq] = TXSCH_SET_FLAG(pfvf_map[schq], NIX_TXSCHQ_CFG_DONE); 2006 1974 } ··· 2717 2667 for (schq = 0; schq < txsch->schq.max; schq++) 2718 2668 txsch->pfvf_map[schq] = TXSCH_MAP(0, NIX_TXSCHQ_FREE); 2719 2669 } 2670 + 2671 + /* Setup a default value of 8192 as DWRR MTU */ 2672 + if (rvu->hw->cap.nix_common_dwrr_mtu) { 2673 + rvu_write64(rvu, blkaddr, NIX_AF_DWRR_RPM_MTU, 2674 + convert_bytes_to_dwrr_mtu(8192)); 2675 + rvu_write64(rvu, blkaddr, NIX_AF_DWRR_SDP_MTU, 2676 + convert_bytes_to_dwrr_mtu(8192)); 2677 + } 2678 + 2720 2679 return 0; 2721 2680 } 2722 2681 ··· 2802 2743 struct nix_hw_info *rsp) 2803 2744 { 2804 2745 u16 pcifunc = req->hdr.pcifunc; 2746 + u64 dwrr_mtu; 2805 2747 int blkaddr; 2806 2748 2807 2749 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); ··· 2815 2755 rvu_get_lmac_link_max_frs(rvu, &rsp->max_mtu); 2816 2756 2817 2757 rsp->min_mtu = NIC_HW_MIN_FRS; 2758 + 2759 + if (!rvu->hw->cap.nix_common_dwrr_mtu) { 2760 + /* Return '1' on OTx2 */ 2761 + rsp->rpm_dwrr_mtu = 1; 2762 + rsp->sdp_dwrr_mtu = 1; 2763 + return 0; 2764 + } 2765 + 2766 + dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU); 2767 + rsp->rpm_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu); 2768 + 2769 + dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_SDP_MTU); 2770 + rsp->sdp_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu); 2771 + 2818 2772 return 0; 2819 2773 } 2820 2774 ··· 3721 3647 return 0; 3722 3648 } 3723 3649 3650 + static void rvu_nix_setup_capabilities(struct rvu *rvu, int blkaddr) 3651 + { 3652 + struct rvu_hwinfo *hw = rvu->hw; 3653 + u64 hw_const; 3654 + 3655 + hw_const = rvu_read64(rvu, blkaddr, NIX_AF_CONST1); 3656 + 3657 + /* On OcteonTx2 DWRR quantum is directly configured into each of 3658 + * the transmit scheduler queues. And PF/VF drivers were free to 3659 + * config any value upto 2^24. 3660 + * On CN10K, HW is modified, the quantum configuration at scheduler 3661 + * queues is in terms of weight. And SW needs to setup a base DWRR MTU 3662 + * at NIX_AF_DWRR_RPM_MTU / NIX_AF_DWRR_SDP_MTU. HW will do 3663 + * 'DWRR MTU * weight' to get the quantum. 3664 + * 3665 + * Check if HW uses a common MTU for all DWRR quantum configs. 3666 + * On OcteonTx2 this register field is '0'. 3667 + */ 3668 + if (((hw_const >> 56) & 0x10) == 0x10) 3669 + hw->cap.nix_common_dwrr_mtu = true; 3670 + } 3671 + 3724 3672 static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw) 3725 3673 { 3726 3674 const struct npc_lt_def_cfg *ltdefs; ··· 3779 3683 err = nix_calibrate_x2p(rvu, blkaddr); 3780 3684 if (err) 3781 3685 return err; 3686 + 3687 + /* Setup capabilities of the NIX block */ 3688 + rvu_nix_setup_capabilities(rvu, blkaddr); 3782 3689 3783 3690 /* Initialize admin queue */ 3784 3691 err = nix_aq_init(rvu, block);
+2
drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
··· 269 269 #define NIX_AF_DEBUG_NPC_RESP_DATAX(a) (0x680 | (a) << 3) 270 270 #define NIX_AF_SMQX_CFG(a) (0x700 | (a) << 16) 271 271 #define NIX_AF_SQM_DBG_CTL_STATUS (0x750) 272 + #define NIX_AF_DWRR_SDP_MTU (0x790) 273 + #define NIX_AF_DWRR_RPM_MTU (0x7A0) 272 274 #define NIX_AF_PSE_CHANNEL_LEVEL (0x800) 273 275 #define NIX_AF_PSE_SHAPER_CFG (0x810) 274 276 #define NIX_AF_TX_EXPR_CREDIT (0x830)
+1 -2
drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
··· 92 92 aq->sq.ena = 1; 93 93 /* Only one SMQ is allocated, map all SQ's to that SMQ */ 94 94 aq->sq.smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0]; 95 - /* FIXME: set based on NIX_AF_DWRR_RPM_MTU*/ 96 - aq->sq.smq_rr_weight = pfvf->netdev->mtu; 95 + aq->sq.smq_rr_weight = mtu_to_dwrr_weight(pfvf, pfvf->max_frs); 97 96 aq->sq.default_chan = pfvf->hw.tx_chan_base; 98 97 aq->sq.sqe_stype = NIX_STYPE_STF; /* Cache SQB */ 99 98 aq->sq.sqb_aura = sqb_aura;
+14
drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
··· 9 9 10 10 #include "otx2_common.h" 11 11 12 + static inline int mtu_to_dwrr_weight(struct otx2_nic *pfvf, int mtu) 13 + { 14 + u32 weight; 15 + 16 + /* On OTx2, since AF returns DWRR_MTU as '1', this logic 17 + * will work on those silicons as well. 18 + */ 19 + weight = mtu / pfvf->hw.dwrr_mtu; 20 + if (mtu % pfvf->hw.dwrr_mtu) 21 + weight += 1; 22 + 23 + return weight; 24 + } 25 + 12 26 void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq); 13 27 void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq, int size, int qidx); 14 28 int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
+17 -6
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
··· 596 596 struct otx2_hw *hw = &pfvf->hw; 597 597 struct nix_txschq_config *req; 598 598 u64 schq, parent; 599 + u64 dwrr_val; 600 + 601 + dwrr_val = mtu_to_dwrr_weight(pfvf, pfvf->max_frs); 599 602 600 603 req = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox); 601 604 if (!req) ··· 624 621 req->num_regs++; 625 622 /* Set DWRR quantum */ 626 623 req->reg[2] = NIX_AF_MDQX_SCHEDULE(schq); 627 - req->regval[2] = DFLT_RR_QTM; 624 + req->regval[2] = dwrr_val; 628 625 } else if (lvl == NIX_TXSCH_LVL_TL4) { 629 626 parent = hw->txschq_list[NIX_TXSCH_LVL_TL3][0]; 630 627 req->reg[0] = NIX_AF_TL4X_PARENT(schq); 631 628 req->regval[0] = parent << 16; 632 629 req->num_regs++; 633 630 req->reg[1] = NIX_AF_TL4X_SCHEDULE(schq); 634 - req->regval[1] = DFLT_RR_QTM; 631 + req->regval[1] = dwrr_val; 635 632 } else if (lvl == NIX_TXSCH_LVL_TL3) { 636 633 parent = hw->txschq_list[NIX_TXSCH_LVL_TL2][0]; 637 634 req->reg[0] = NIX_AF_TL3X_PARENT(schq); 638 635 req->regval[0] = parent << 16; 639 636 req->num_regs++; 640 637 req->reg[1] = NIX_AF_TL3X_SCHEDULE(schq); 641 - req->regval[1] = DFLT_RR_QTM; 638 + req->regval[1] = dwrr_val; 642 639 } else if (lvl == NIX_TXSCH_LVL_TL2) { 643 640 parent = hw->txschq_list[NIX_TXSCH_LVL_TL1][0]; 644 641 req->reg[0] = NIX_AF_TL2X_PARENT(schq); ··· 646 643 647 644 req->num_regs++; 648 645 req->reg[1] = NIX_AF_TL2X_SCHEDULE(schq); 649 - req->regval[1] = TXSCH_TL1_DFLT_RR_PRIO << 24 | DFLT_RR_QTM; 646 + req->regval[1] = TXSCH_TL1_DFLT_RR_PRIO << 24 | dwrr_val; 650 647 651 648 req->num_regs++; 652 649 req->reg[2] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, ··· 659 656 * For VF this is always ignored. 660 657 */ 661 658 662 - /* Set DWRR quantum */ 659 + /* On CN10K, if RR_WEIGHT is greater than 16384, HW will 660 + * clip it to 16384, so configuring a 24bit max value 661 + * will work on both OTx2 and CN10K. 662 + */ 663 663 req->reg[0] = NIX_AF_TL1X_SCHEDULE(schq); 664 664 req->regval[0] = TXSCH_TL1_DFLT_RR_QTM; 665 665 ··· 809 803 aq->sq.ena = 1; 810 804 /* Only one SMQ is allocated, map all SQ's to that SMQ */ 811 805 aq->sq.smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0]; 812 - aq->sq.smq_rr_quantum = DFLT_RR_QTM; 806 + aq->sq.smq_rr_quantum = mtu_to_dwrr_weight(pfvf, pfvf->max_frs); 813 807 aq->sq.default_chan = pfvf->hw.tx_chan_base; 814 808 aq->sq.sqe_stype = NIX_STYPE_STF; /* Cache SQB */ 815 809 aq->sq.sqb_aura = sqb_aura; ··· 1674 1668 * SMQ errors 1675 1669 */ 1676 1670 max_mtu = rsp->max_mtu - 8 - OTX2_ETH_HLEN; 1671 + 1672 + /* Also save DWRR MTU, needed for DWRR weight calculation */ 1673 + pfvf->hw.dwrr_mtu = rsp->rpm_dwrr_mtu; 1674 + if (!pfvf->hw.dwrr_mtu) 1675 + pfvf->hw.dwrr_mtu = 1; 1677 1676 } 1678 1677 1679 1678 out:
+1
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
··· 181 181 /* NIX */ 182 182 u16 txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; 183 183 u16 matchall_ipolicer; 184 + u32 dwrr_mtu; 184 185 185 186 /* HW settings, coalescing etc */ 186 187 u16 rx_chan_base;