diff --git a/include/core/enet_mod_hostport.h b/include/core/enet_mod_hostport.h index 99b300be..5333b93a 100644 --- a/include/core/enet_mod_hostport.h +++ b/include/core/enet_mod_hostport.h @@ -222,11 +222,11 @@ typedef enum EnetHostPort_Ioctl_e ENET_HOSTPORT_IOCTL_SET_CREDIT_BASED_SHAPING = ENET_HOSTPORT_PUBLIC_IOCTL(15U), /*! - * \brief Get Idleslope of Credit Based Shaper on Host Port. + * \brief Get Idleslope of Credit Based Shaper on Host Port queue. * * IOCTL parameters: - * - inArgs: None - * - outArgs: #EnetPort_CreditBasedShapingCfg + * - inArgs: uint32_t + * - outArgs: uint64_t */ ENET_HOSTPORT_IOCTL_GET_CREDIT_BASED_SHAPING = ENET_HOSTPORT_PUBLIC_IOCTL(16U), } EnetHostPort_Ioctl; diff --git a/include/core/enet_mod_macport.h b/include/core/enet_mod_macport.h index 1b8fdd13..df0bb41c 100644 --- a/include/core/enet_mod_macport.h +++ b/include/core/enet_mod_macport.h @@ -211,17 +211,17 @@ typedef enum EnetMacPort_Ioctl_e * \brief Set Idleslope for Credit Based Shaper on MAC Port. * * IOCTL parameters: - * - inArgs: #EnetMacPort_CreditBasedShaperInArgs + * - inArgs: #EnetMacPort_SetCreditBasedShaperInArgs * - outArgs: None */ ENET_MACPORT_IOCTL_SET_CREDIT_BASED_SHAPING = ENET_MACPORT_PUBLIC_IOCTL(13U), /*! - * \brief Get Idleslope of Credit Based Shaper on MAC Port. + * \brief Get Idleslope of Credit Based Shaper on MAC Port queue. * * IOCTL parameters: - * - inArgs: #EnetMacPort_GenericInArgs - * - outArgs: #EnetPort_CreditBasedShapingCfg + * - inArgs: #EnetMacPort_GetCreditBasedShaperInArgs + * - outArgs: uint64_t */ ENET_MACPORT_IOCTL_GET_CREDIT_BASED_SHAPING = ENET_MACPORT_PUBLIC_IOCTL(14U), @@ -537,14 +537,26 @@ typedef struct EnetMacPort_EnableEgressTrafficShapingInArgs_s /*! * \brief Input args for #ENET_MACPORT_IOCTL_SET_CREDIT_BASED_SHAPING command. */ -typedef struct EnetMacPort_CreditBasedShaperInArgs_s +typedef struct EnetMacPort_SetCreditBasedShaperInArgs_s { /*! Port number */ Enet_MacPort macPort; /*! Credit based shaper configuration */ EnetPort_CreditBasedShapingCfg cbsCfg; -} EnetMacPort_CreditBasedShaperInArgs; +} EnetMacPort_SetCreditBasedShaperInArgs; + +/*! + * \brief Input args for #ENET_MACPORT_IOCTL_GET_CREDIT_BASED_SHAPING command. + */ +typedef struct EnetMacPort_GetCreditBasedShaperInArgs_s +{ + /*! Port number */ + Enet_MacPort macPort; + + /*! Priority queue number */ + uint32_t trafficClass; +} EnetMacPort_GetCreditBasedShaperInArgs; /*! * \brief MacPort IET Verification status diff --git a/include/core/enet_mod_port.h b/include/core/enet_mod_port.h index d154ab94..bf677521 100755 --- a/include/core/enet_mod_port.h +++ b/include/core/enet_mod_port.h @@ -105,8 +105,11 @@ typedef struct EnetPort_TrafficShapingRates_s */ typedef struct EnetPort_CreditBasedShapingCfg_s { - /*! idleSlope for CBS on each switch queue priority */ - uint64_t idleSlope[ENET_PRI_NUM]; + /*! Priority queue number */ + uint32_t queueNum; + + /*! idleSlope for CBS for the switch queue priority */ + uint64_t idleSlope; } EnetPort_CreditBasedShapingCfg; /*! diff --git a/src/core/enet.c b/src/core/enet.c index 6a5084da..0c19f412 100644 --- a/src/core/enet.c +++ b/src/core/enet.c @@ -291,8 +291,8 @@ static Enet_IoctlValidate gEnetHostPort_ioctlValidate[] = 0U), ENET_IOCTL_VALID_PRMS(ENET_HOSTPORT_IOCTL_GET_CREDIT_BASED_SHAPING, - 0U, - sizeof(EnetPort_CreditBasedShapingCfg)), + sizeof(uint32_t), + sizeof(uint64_t)), }; /* Public MAC port IOCTL validation data. */ @@ -351,12 +351,12 @@ static Enet_IoctlValidate gEnetMacPort_ioctlValidate[] = sizeof(EnetMacPort_LinkCfg)), ENET_IOCTL_VALID_PRMS(ENET_MACPORT_IOCTL_SET_CREDIT_BASED_SHAPING, - sizeof(EnetMacPort_CreditBasedShaperInArgs), + sizeof(EnetMacPort_SetCreditBasedShaperInArgs), 0U), ENET_IOCTL_VALID_PRMS(ENET_MACPORT_IOCTL_GET_CREDIT_BASED_SHAPING, - sizeof(EnetMacPort_GenericInArgs), - sizeof(EnetPort_CreditBasedShapingCfg)), + sizeof(EnetMacPort_GetCreditBasedShaperInArgs), + sizeof(uint64_t)), ENET_IOCTL_VALID_PRMS(ENET_MACPORT_IOCTL_IET_RELEASE_PREEMPT_TRAFFIC, sizeof(EnetMacPort_GenericInArgs), diff --git a/src/mod/cpsw_hostport_ioctl.c b/src/mod/cpsw_hostport_ioctl.c index 516abd9d..a6f48bdb 100644 --- a/src/mod/cpsw_hostport_ioctl.c +++ b/src/mod/cpsw_hostport_ioctl.c @@ -316,22 +316,23 @@ int32_t CpswHostPort_ioctl_handler_ENET_HOSTPORT_IOCTL_SET_CREDIT_BASED_SHAPING( #if ENET_CFG_IS_ON(CPSW_HOSTPORT_TRAFFIC_SHAPING) const EnetPort_CreditBasedShapingCfg *inArgs = (const EnetPort_CreditBasedShapingCfg *)prms->inArgs; - uint32_t cppiClkFreqHz,i; + uint32_t cppiClkFreqHz; EnetPort_TrafficShapingCfg trafficShapingCfg; + status = (inArgs->queueNum < ENET_PRI_NUM) ? ENET_SOK : ENET_EINVALIDPARAMS; cppiClkFreqHz = EnetSoc_getClkFreq(hPort->enetType, hPort->instId, CPSW_CPPI_CLK); status = (cppiClkFreqHz != 0) ? ENET_SOK : ENET_EINVALIDPARAMS; if (status == ENET_SOK) { - for (i = 0U; i < ENET_PRI_NUM; i++) - { - trafficShapingCfg.rates[i].committedRateBitsPerSec = inArgs->idleSlope[i]; - trafficShapingCfg.rates[i].excessRateBitsPerSec = 0U; - } - - status = CpswHostPort_setTrafficShaping(regs, &trafficShapingCfg, cppiClkFreqHz); - ENETTRACE_ERR_IF(status != ENET_SOK, "Failed to set Credit based shaping: %d\n", status); + status = CpswHostPort_getTrafficShaping(regs, &trafficShapingCfg, cppiClkFreqHz); + ENETTRACE_ERR_IF(status != ENET_SOK, "Failed to get traffic shaping: %d\n", status); } + if (status == ENET_SOK) + { + trafficShapingCfg.rates[inArgs->queueNum].committedRateBitsPerSec = inArgs->idleSlope; + } + status = CpswHostPort_setTrafficShaping(regs, &trafficShapingCfg, cppiClkFreqHz); + ENETTRACE_ERR_IF(status != ENET_SOK, "Failed to set Credit based shaping: %d\n", status); #else status = ENET_ENOTSUPPORTED; @@ -343,19 +344,32 @@ int32_t CpswHostPort_ioctl_handler_ENET_HOSTPORT_IOCTL_GET_CREDIT_BASED_SHAPING( { int32_t status = ENET_SOK; #if ENET_CFG_IS_ON(CPSW_HOSTPORT_TRAFFIC_SHAPING) - EnetPort_CreditBasedShapingCfg *cbsCfg = (EnetPort_CreditBasedShapingCfg *)prms->outArgs; - uint32_t cppiClkFreqHz,i; - EnetPort_TrafficShapingCfg trafficShapingCfg; + uint32_t *priority = (uint32_t *)prms->inArgs; + uint64_t *idleSlope = (uint64_t *)prms->outArgs; + uint32_t cir, eir, cppiClkFreqHz; + uint64_t cirBps, eirBps; cppiClkFreqHz = EnetSoc_getClkFreq(hPort->enetType, hPort->instId, CPSW_CPPI_CLK); + CSL_CPSW_getCppiPriCirEir(regs, *priority, &cir, &eir); - status = CpswHostPort_getTrafficShaping(regs, &trafficShapingCfg, cppiClkFreqHz); - ENETTRACE_ERR_IF(status != ENET_SOK, "Failed to get traffic shaping: %d\n", status); + cirBps = CpswHostPort_mapCntToBw(cir, cppiClkFreqHz); + eirBps = CpswHostPort_mapCntToBw(eir, cppiClkFreqHz); - for (i = 0U; i < ENET_PRI_NUM; i++) + /* CIR must be non-zero if EIR is non-zero */ + if ((cirBps == 0ULL) && (eirBps != 0ULL)) { - cbsCfg->idleSlope[i] = trafficShapingCfg.rates[i].committedRateBitsPerSec; + ENETTRACE_ERR("HOSTPORT: EIR is enabled (%llubps = %u) but CIR is not (%llubps = %u) " + "for priority %u\n", eirBps, eir, cirBps, cir, *priority); + status = ENET_EUNEXPECTED; } + + ENETTRACE_DBG("HOSTPORT: rate limiting %s for priority %u, CIR=%llubps (%u) EIR=%llubps (%u)\n", + (cir != 0U) ? "enabled" : "disabled", *priority, cirBps, cir, eirBps, eir); + + ENETTRACE_ERR_IF(status != ENET_SOK, "Failed to get traffic shaping: %d\n", status); + + *idleSlope = cirBps; + #else status = ENET_ENOTSUPPORTED; #endif diff --git a/src/mod/cpsw_macport_ioctl.c b/src/mod/cpsw_macport_ioctl.c index 7bf0d0f6..21f64d7d 100755 --- a/src/mod/cpsw_macport_ioctl.c +++ b/src/mod/cpsw_macport_ioctl.c @@ -83,6 +83,12 @@ /*! \brief Port Speed Auto Enable Mask*/ #define CPSW_MACPORT_SPEED_AUTO_ENABLE_MASK (0x00000001) +/*! \brief Port Speed 1Gbps */ +#define CPSW_MACPORT_SPEED_1G (1000000000U) + +/*! \brief Port Speed 100Mbps */ +#define CPSW_MACPORT_SPEED_100M (100000000U) + #if ENET_CFG_IS_ON(CPSW_MACPORT_TRAFFIC_SHAPING) static uint64_t CpswMacPort_mapBwToCnt(uint64_t rateInBps, uint32_t cppiClkFreqHz); @@ -102,6 +108,12 @@ static int32_t CpswMacPort_getTrafficShaping(CSL_Xge_cpswRegs *regs, Enet_MacPort macPort, EnetPort_TrafficShapingCfg *cfg, uint32_t cppiClkFreqHz); + +static int32_t CpswMacPort_setPriorityTrafficShaping(CSL_Xge_cpswRegs *regs, + Enet_MacPort macPort, + uint32_t priority, + uint64_t cirBps, + uint32_t cppiClkFreqHz); #endif #if ENET_CFG_IS_ON(CPSW_IET_INCL) @@ -1025,26 +1037,20 @@ int32_t CpswMacPort_ioctl_handler_ENET_MACPORT_IOCTL_SET_CREDIT_BASED_SHAPING(Cp { int32_t status = ENET_SOK; #if ENET_CFG_IS_ON(CPSW_MACPORT_TRAFFIC_SHAPING) - const EnetMacPort_CreditBasedShaperInArgs *inArgs = - (const EnetMacPort_CreditBasedShaperInArgs *)prms->inArgs; + const EnetMacPort_SetCreditBasedShaperInArgs *inArgs = + (const EnetMacPort_SetCreditBasedShaperInArgs *)prms->inArgs; Enet_MacPort macPort = hPort->macPort; - uint32_t cppiClkFreqHz,i; - EnetPort_TrafficShapingCfg trafficShapingCfg; + uint32_t cppiClkFreqHz; Enet_devAssert(macPort == inArgs->macPort, "MAC %u: Port mismatch %u\n", ENET_MACPORT_ID(macPort), inArgs->macPort); + status = (inArgs->cbsCfg.queueNum < ENET_PRI_NUM) ? ENET_SOK : ENET_EINVALIDPARAMS; cppiClkFreqHz = EnetSoc_getClkFreq(hPort->enetType, hPort->instId, CPSW_CPPI_CLK); status = (cppiClkFreqHz != 0) ? ENET_SOK : ENET_EINVALIDPARAMS; if (status == ENET_SOK) { - for (i = 0U; i < ENET_PRI_NUM; i++) - { - trafficShapingCfg.rates[i].committedRateBitsPerSec = inArgs->cbsCfg.idleSlope[i]; - trafficShapingCfg.rates[i].excessRateBitsPerSec = 0U; - } - - status = CpswMacPort_setTrafficShaping(regs, macPort, &trafficShapingCfg, cppiClkFreqHz); + status = CpswMacPort_setPriorityTrafficShaping(regs, macPort, inArgs->cbsCfg.queueNum, inArgs->cbsCfg.idleSlope, cppiClkFreqHz); ENETTRACE_ERR_IF(status != ENET_SOK, "Failed to set Credit based shaping: %d\n", status); } @@ -1058,24 +1064,41 @@ int32_t CpswMacPort_ioctl_handler_ENET_MACPORT_IOCTL_GET_CREDIT_BASED_SHAPING(Cp { int32_t status = ENET_SOK; #if ENET_CFG_IS_ON(CPSW_MACPORT_TRAFFIC_SHAPING) - EnetMacPort_GenericInArgs *inArgs = (EnetMacPort_GenericInArgs *)prms->inArgs; - EnetPort_CreditBasedShapingCfg *cbsCfg = (EnetPort_CreditBasedShapingCfg *)prms->outArgs; + EnetMacPort_GetCreditBasedShaperInArgs *inArgs = (EnetMacPort_GetCreditBasedShaperInArgs *)prms->inArgs; + uint64_t *idleSlope = (uint64_t *)prms->outArgs; Enet_MacPort macPort = hPort->macPort; - uint32_t cppiClkFreqHz,i; - EnetPort_TrafficShapingCfg trafficShapingCfg; + uint32_t portNum = ENET_MACPORT_NORM(macPort); + uint32_t portId = ENET_MACPORT_ID(macPort); + uint32_t cir, eir, cppiClkFreqHz; + uint64_t cirBps, eirBps; + ENETTRACE_VAR(portId); Enet_devAssert(macPort == inArgs->macPort, "MAC %u: Port mismatch %u\n", ENET_MACPORT_ID(macPort), inArgs->macPort); cppiClkFreqHz = EnetSoc_getClkFreq(hPort->enetType, hPort->instId, CPSW_CPPI_CLK); + CSL_CPSW_getPriCirEir(regs, portNum, inArgs->trafficClass, &cir, &eir); - status = CpswMacPort_getTrafficShaping(regs, macPort, &trafficShapingCfg, cppiClkFreqHz); - ENETTRACE_ERR_IF(status != ENET_SOK, "Failed to get traffic shaping: %d\n", status); + cirBps = CpswMacPort_mapCntToBw(cir, cppiClkFreqHz); + eirBps = CpswMacPort_mapCntToBw(eir, cppiClkFreqHz); - for (i = 0U; i < ENET_PRI_NUM; i++) + /* CIR must be non-zero if EIR is non-zero */ + if ((cirBps == 0ULL) && (eirBps != 0ULL)) { - cbsCfg->idleSlope[i] = trafficShapingCfg.rates[i].committedRateBitsPerSec; + ENETTRACE_ERR("MAC %u: EIR is enabled (%llubps = %u) but CIR is not (%llubps = %u) " + "for priority %u\n", + portId, eirBps, eir, cirBps, cir, inArgs->trafficClass); + status = ENET_EUNEXPECTED; } + + ENETTRACE_DBG("MAC %u: rate limiting %s for priority %u, CIR=%llubps (%u) EIR=%llubps (%u)\n", + portId, (cir != 0U) ? "enabled" : "disabled", + inArgs->trafficClass, cirBps, cir, eirBps, eir); + + ENETTRACE_ERR_IF(status != ENET_SOK, "Failed to get traffic shaping: %d\n", status); + + *idleSlope = cirBps; + #else status = ENET_ENOTSUPPORTED; #endif @@ -1112,6 +1135,72 @@ static uint64_t CpswMacPort_mapCntToBw(uint32_t cntVal, return ((uint64_t)cntVal * cppiClkFreqHz) / CPSW_MACPORT_RATELIM_DIV; } +static int32_t CpswMacPort_setPriorityTrafficShaping(CSL_Xge_cpswRegs *regs, + Enet_MacPort macPort, + uint32_t priority, + uint64_t cirBps, + uint32_t cppiClkFreqHz) +{ + uint64_t cir, eir; + int32_t status = ENET_SOK; + EnetPort_TrafficShapingCfg shapingCfg; + uint64_t totalCirBps = 0U; + uint64_t linkSpeedBps = 0U; + EnetMacPort_LinkCfg linkCfg; + uint32_t portId = ENET_MACPORT_ID(macPort); + uint32_t i; + + cir = CpswMacPort_mapBwToCnt(cirBps, cppiClkFreqHz); + eir = 0U; + + ENETTRACE_VAR(portId); + CpswMacPort_getLinkCfg(regs, macPort, &linkCfg); + if(linkCfg.speed == ENET_SPEED_1GBIT) + { + linkSpeedBps = CPSW_MACPORT_SPEED_1G; + } + else if(linkCfg.speed == ENET_SPEED_100MBIT) + { + linkSpeedBps = CPSW_MACPORT_SPEED_100M; + } + if (cir > 0x0FFFFFFFULL) + { + ENETTRACE_ERR("MAC %u: invalid CIR=%llu (%llubps) for priority %u\n", + portId, cir, cirBps, priority); + status = ENET_EINVALIDPARAMS; + } + if(status == ENET_SOK) + { + status = CpswMacPort_getTrafficShaping(regs, macPort, &shapingCfg, cppiClkFreqHz); + ENETTRACE_ERR_IF(status != ENET_SOK, "Failed to get traffic shaping: %d\n", status); + if(status == ENET_SOK) + { + if(cirBps > shapingCfg.rates[priority].committedRateBitsPerSec) + { + for (i = 0U; i < ENET_PRI_NUM; i++) + { + if(i == priority) continue; + totalCirBps += shapingCfg.rates[i].committedRateBitsPerSec; + } + if (totalCirBps + cirBps >= linkSpeedBps) + { + ENETTRACE_ERR("MAC %u: The sum of CBS bandwidths can't exceed link speed \n", portId); + status = ENET_EINVALIDPARAMS; + } + } + } + } + if(status == ENET_SOK) + { + shapingCfg.rates[priority].committedRateBitsPerSec = cirBps; + shapingCfg.rates[priority].excessRateBitsPerSec = 0U; + /* Verify whether the higher priorities have CBS enabled */ + status = CpswMacPort_setTrafficShaping(regs, macPort, &shapingCfg, cppiClkFreqHz); + } + + return status; +} + static int32_t CpswMacPort_setTrafficShaping(CSL_Xge_cpswRegs *regs, Enet_MacPort macPort, const EnetPort_TrafficShapingCfg *cfg,