blob: 31321601f3f9cf346e1e814224dad1c21bb5c565 [file] [log] [blame]
#include <Copyright.h>
/*******************************************************************************
* gtPIRL.c
*
* DESCRIPTION:
* API definitions for PIRL Resources
*
* DEPENDENCIES:
*
* FILE REVISION NUMBER:
*******************************************************************************/
#include <msApi.h>
#include <gtSem.h>
#include <gtHwCntl.h>
#include <gtDrvSwRegs.h>
/****************************************************************************/
/* STATS operation function declaration. */
/****************************************************************************/
static GT_STATUS pirlOperationPerform
(
IN GT_QD_DEV *dev,
IN GT_PIRL_OPERATION pirlOp,
INOUT GT_PIRL_OP_DATA *opData
);
static GT_STATUS pirlInitialize
(
IN GT_QD_DEV *dev
);
static GT_STATUS pirlInitIRLUnit
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit
);
static GT_STATUS pirlDataToResource
(
IN GT_QD_DEV *dev,
IN GT_PIRL_DATA *pirlData,
OUT GT_PIRL_RESOURCE *res
);
static GT_STATUS pirlResourceToData
(
IN GT_QD_DEV *dev,
IN GT_PIRL_RESOURCE *res,
OUT GT_PIRL_DATA *pirlData
);
static GT_STATUS pirlWriteResource
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
IN GT_PIRL_RESOURCE *res
);
static GT_STATUS pirlReadResource
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
OUT GT_PIRL_RESOURCE *res
);
static GT_STATUS pirlSetPortVec
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
IN GT_U32 portVec
);
static GT_STATUS pirlGetPortVec
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
OUT GT_U32 *portVec
);
static GT_STATUS pirlSetFcMode
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_PIRL_FC_DEASSERT mode
);
/*******************************************************************************
* gpirlActivate
*
* DESCRIPTION:
* This routine activates Ingress Rate Limiting for the given ports by
* initializing a resource bucket, assigning ports, and configuring
* Bucket Parameters.
*
* INPUTS:
* irlUnit - bucket to be used (0 ~ 11).
* portVec - the list of ports that share the bucket.
* pirlData - PIRL resource parameters.
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_BAD_PARAM - if invalid parameter is given
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
* None
*
*******************************************************************************/
GT_STATUS gpirlActivate
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
IN GT_U32 portVec,
IN GT_PIRL_DATA *pirlData
)
{
GT_STATUS retVal;
GT_PORT_STP_STATE pState[MAX_SWITCH_PORTS];
GT_LPORT port;
GT_PIRL_OPERATION op;
GT_PIRL_OP_DATA opData;
GT_PIRL_RESOURCE pirlRes;
DBG_INFO(("gpirlActivate Called.\n"));
/* check if device supports this feature */
if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
{
DBG_INFO(("GT_NOT_SUPPORTED\n"));
return GT_NOT_SUPPORTED;
}
/* check if the given bucket number is valid */
if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
{
DBG_INFO(("GT_BAD_PARAM irlUnit\n"));
return GT_BAD_PARAM;
}
/* check if the given portVec is valid */
if ((!portVec) || (portVec >= (GT_U32)(1<<dev->numOfPorts)))
{
DBG_INFO(("GT_BAD_PARAM portVec\n"));
return GT_BAD_PARAM;
}
/* set or reset port's ingress resource bit based on the portVec */
retVal = pirlSetPortVec(dev, irlUnit, portVec);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
/* Disable ports that share the bucket */
for(port=0; port<dev->numOfPorts; port++)
{
if(!GT_IS_PORT_SET(portVec,port))
continue;
retVal = gstpGetPortState(dev, port, &pState[port]);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
retVal = gstpSetPortState(dev, port, GT_PORT_DISABLE);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
}
/* Program Tuning register */
op = PIRL_WRITE_RESOURCE;
opData.irlUnit = irlUnit;
opData.irlReg = 0xF;
opData.irlData = 0x7;
retVal = pirlOperationPerform(dev,op,&opData);
if(retVal != GT_OK)
{
DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
return retVal;
}
/* Program the Ingress Rate Resource Parameters */
retVal = pirlDataToResource(dev,pirlData,&pirlRes);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL Data to PIRL Resource conversion failed.\n"));
return retVal;
}
retVal = pirlWriteResource(dev,irlUnit,&pirlRes);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL Write Resource failed.\n"));
return retVal;
}
/* Initialize internal counters */
retVal = pirlInitIRLUnit(dev,irlUnit);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL Write Resource failed.\n"));
return retVal;
}
/* Program PirlFCMode for each port that shares Bucket */
if (pirlRes.ebsLimitAction == ESB_LIMIT_ACTION_FC)
{
for(port=0; port<dev->numOfPorts; port++)
{
if(!GT_IS_PORT_SET(portVec,port))
continue;
retVal = pirlSetFcMode(dev,port,pirlData->fcDeassertMode[port]);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL FC Mode set failed.\n"));
return retVal;
}
}
}
/* Set the ports in their original state */
for(port=0; port<dev->numOfPorts; port++)
{
if(!GT_IS_PORT_SET(portVec,port))
continue;
retVal = gstpSetPortState(dev, port, pState[port]);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
}
DBG_INFO(("OK.\n"));
return GT_OK;
}
/*******************************************************************************
* gpirlDeactivate
*
* DESCRIPTION:
* This routine deactivates Ingress Rate Limiting for the given bucket.
* It simply removes every ports from the Ingress Rate Resource.
* It is assumed that gpirlActivate has been successfully called with
* the irlUnit before this function is called.
*
* INPUTS:
* irlUnit - bucket to be used (0 ~ 11).
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_BAD_PARAM - if invalid parameter is given
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
* None
*
*******************************************************************************/
GT_STATUS gpirlDeactivate
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit
)
{
GT_STATUS retVal;
DBG_INFO(("gpirlDectivate Called.\n"));
/* check if device supports this feature */
if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
{
DBG_INFO(("GT_NOT_SUPPORTED\n"));
return GT_NOT_SUPPORTED;
}
/* check if the given bucket number is valid */
if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
{
DBG_INFO(("GT_BAD_PARAM\n"));
return GT_BAD_PARAM;
}
/* reset port's ingress resource bit */
retVal = pirlSetPortVec(dev, irlUnit, 0);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
DBG_INFO(("OK.\n"));
return GT_OK;
}
/*******************************************************************************
* gpirlUpdateParam
*
* DESCRIPTION:
* This routine updates IRL Parameter.
* It is assumed that gpirlActivate has been successfully called with
* the given irlUnit before this function is called.
*
* INPUTS:
* irlUnit - bucket to be used (0 ~ 11).
* pirlData - PIRL resource parameters.
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_BAD_PARAM - if invalid parameter is given
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
* None
*
*******************************************************************************/
GT_STATUS gpirlUpdateParam
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
IN GT_PIRL_DATA *pirlData
)
{
GT_STATUS retVal;
GT_PORT_STP_STATE pState[MAX_SWITCH_PORTS];
GT_LPORT port;
GT_PIRL_RESOURCE pirlRes;
GT_U32 portVec;
DBG_INFO(("gpirlUpdateParam Called.\n"));
/* check if device supports this feature */
if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
{
DBG_INFO(("GT_NOT_SUPPORTED\n"));
return GT_NOT_SUPPORTED;
}
/* check if the given bucket number is valid */
if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
{
DBG_INFO(("GT_BAD_PARAM\n"));
return GT_BAD_PARAM;
}
/* get port list that share ingress resource */
retVal = pirlGetPortVec(dev, irlUnit, &portVec);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
/* check if the given portVec is valid */
if (!portVec)
{
DBG_INFO(("IRL Unit not Activated\n"));
return GT_FAIL;
}
/* Disable ports that share the bucket */
for(port=0; port<dev->numOfPorts; port++)
{
if(!GT_IS_PORT_SET(portVec,port))
continue;
retVal = gstpGetPortState(dev, port, &pState[port]);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
retVal = gstpSetPortState(dev, port, GT_PORT_DISABLE);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
}
/* Program the Ingress Rate Resource Parameters */
retVal = pirlDataToResource(dev,pirlData,&pirlRes);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL Data to PIRL Resource conversion failed.\n"));
return retVal;
}
retVal = pirlWriteResource(dev,irlUnit,&pirlRes);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL Write Resource failed.\n"));
return retVal;
}
/* Initialize internal counrters for the bucket */
retVal = pirlInitIRLUnit(dev,irlUnit);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL Write Resource failed.\n"));
return retVal;
}
/* Program PirlFCMode for each port that shares Bucket */
if (pirlRes.ebsLimitAction == ESB_LIMIT_ACTION_FC)
{
for(port=0; port<dev->numOfPorts; port++)
{
if(!GT_IS_PORT_SET(portVec,port))
continue;
retVal = pirlSetFcMode(dev,port,pirlData->fcDeassertMode[port]);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL FC Mode set failed.\n"));
return retVal;
}
}
}
/* Set the ports in their original state */
for(port=0; port<dev->numOfPorts; port++)
{
if(!GT_IS_PORT_SET(portVec,port))
continue;
retVal = gstpSetPortState(dev, port, pState[port]);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
}
DBG_INFO(("OK.\n"));
return GT_OK;
}
/*******************************************************************************
* gpirlReadParam
*
* DESCRIPTION:
* This routine retrieves IRL Parameter.
* It is assumed that gpirlActivate has been successfully called with
* the given irlUnit before this function is called.
*
* INPUTS:
* irlUnit - bucket to be used (0 ~ 11).
*
* OUTPUTS:
* pirlData - PIRL resource parameters.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_BAD_PARAM - if invalid parameter is given
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
* None
*
*******************************************************************************/
GT_STATUS gpirlReadParam
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
OUT GT_PIRL_DATA *pirlData
)
{
GT_STATUS retVal;
GT_LPORT port;
GT_PIRL_RESOURCE pirlRes;
GT_U32 portVec;
DBG_INFO(("gpirlReadParam Called.\n"));
/* check if device supports this feature */
if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
{
DBG_INFO(("GT_NOT_SUPPORTED\n"));
return GT_NOT_SUPPORTED;
}
/* check if the given bucket number is valid */
if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
{
DBG_INFO(("GT_BAD_PARAM\n"));
return GT_BAD_PARAM;
}
/* get port list that share ingress resource */
retVal = pirlGetPortVec(dev, irlUnit, &portVec);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
/* check if the given portVec is valid */
if (!portVec)
{
DBG_INFO(("IRL Unit not Activated\n"));
return GT_FAIL;
}
/* Read the Ingress Rate Resource Parameters */
retVal = pirlReadResource(dev,irlUnit,&pirlRes);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL Read Resource failed.\n"));
return retVal;
}
retVal = pirlResourceToData(dev,&pirlRes,pirlData);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL Resource to PIRL Data conversion failed.\n"));
return retVal;
}
/* Program PirlFCMode for each port that shares Bucket */
if (pirlRes.ebsLimitAction == ESB_LIMIT_ACTION_FC)
{
for(port=0; port<dev->numOfPorts; port++)
{
if(!GT_IS_PORT_SET(portVec,port))
continue;
retVal = grcGetPirlFcMode(dev,port,&pirlData->fcDeassertMode[port]);
if(retVal != GT_OK)
{
DBG_INFO(("PIRL FC Mode get failed.\n"));
return retVal;
}
}
}
DBG_INFO(("OK.\n"));
return GT_OK;
}
/*******************************************************************************
* gpirlUpdatePortVec
*
* DESCRIPTION:
* This routine updates port list that share the bucket.
* It is assumed that gpirlActivate has been successfully called with
* the given irlUnit before this function is called.
*
* INPUTS:
* irlUnit - bucket to be used (0 ~ 11).
* portVec - the list of ports that share the bucket.
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_BAD_PARAM - if invalid parameter is given
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
* None
*
*******************************************************************************/
GT_STATUS gpirlUpdatePortVec
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
IN GT_U32 portVec
)
{
GT_STATUS retVal;
GT_U32 tmpVec;
DBG_INFO(("gpirlActivate Called.\n"));
/* check if device supports this feature */
if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
{
DBG_INFO(("GT_NOT_SUPPORTED\n"));
return GT_NOT_SUPPORTED;
}
/* check if the given bucket number is valid */
if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
{
DBG_INFO(("GT_BAD_PARAM\n"));
return GT_BAD_PARAM;
}
/* check if the given portVec is valid */
if ((!portVec) || (portVec > (GT_U32)(1<<dev->numOfPorts)))
{
DBG_INFO(("GT_BAD_PARAM\n"));
return GT_BAD_PARAM;
}
/* get port list that share ingress resource */
retVal = pirlGetPortVec(dev, irlUnit, &tmpVec);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
/* check if the given portVec is valid */
if (!tmpVec)
{
DBG_INFO(("IRL Unit not Activated\n"));
return GT_FAIL;
}
/* set or reset port's ingress resource bit based on the portVec */
retVal = pirlSetPortVec(dev, irlUnit, portVec);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
DBG_INFO(("OK.\n"));
return GT_OK;
}
/*******************************************************************************
* gpirlReadPortVec
*
* DESCRIPTION:
* This routine retrieves port list that share the bucket.
* It is assumed that gpirlActivate has been successfully called with
* the given irlUnit before this function is called.
*
* INPUTS:
* irlUnit - bucket to be used (0 ~ 11).
*
* OUTPUTS:
* portVec - the list of ports that share the bucket.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_BAD_PARAM - if invalid parameter is given
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
* None
*
*******************************************************************************/
GT_STATUS gpirlReadPortVec
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
OUT GT_U32 *portVec
)
{
GT_STATUS retVal;
DBG_INFO(("gpirlReadPortVec Called.\n"));
/* check if device supports this feature */
if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
{
DBG_INFO(("GT_NOT_SUPPORTED\n"));
return GT_NOT_SUPPORTED;
}
/* check if the given bucket number is valid */
if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
{
DBG_INFO(("GT_BAD_PARAM\n"));
return GT_BAD_PARAM;
}
/* get port list that share ingress resource */
retVal = pirlGetPortVec(dev, irlUnit, portVec);
if(retVal != GT_OK)
{
DBG_INFO(("Getting Port State failed\n"));
return retVal;
}
/* check if the given portVec is valid */
if (!*portVec)
{
DBG_INFO(("IRL Unit not Activated\n"));
return GT_FAIL;
}
DBG_INFO(("OK.\n"));
return GT_OK;
}
/*******************************************************************************
* grcGetPirlFcMode
*
* DESCRIPTION:
* This routine gets Port Ingress Rate Limit Flow Control mode.
* When EBSLimitAction is programmed to generate a flow control message,
* the deassertion of flow control is controlled by this mode.
* GT_PIRL_FC_DEASSERT_EMPTY:
* De-assert when the ingress rate resource has become empty
* GT_PIRL_FC_DEASSERT_CBS_LIMIT
* De-assert when the ingress rate resource has enough room as
* specified by the CBSLimit.
* Please refer to GT_PIRL_RESOURCE structure for EBSLimitAction and
* CBSLimit.
*
* INPUTS:
* port - logical port number
*
* OUTPUTS:
* mode - GT_PIRL_FC_DEASSERT enum type
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS grcGetPirlFcMode
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
OUT GT_PIRL_FC_DEASSERT *mode
)
{
GT_U16 data;
GT_STATUS retVal; /* Functions return value. */
GT_U8 hwPort; /* Physical port. */
DBG_INFO(("grcSetDaNrlEn Called.\n"));
hwPort = GT_LPORT_2_PORT(port);
/* check if the given Switch supports this feature. */
if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
{
DBG_INFO(("GT_NOT_SUPPORTED\n"));
return GT_NOT_SUPPORTED;
}
/* Get the PirlFcMode. */
retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,12,1,&data);
if(retVal != GT_OK)
{
DBG_INFO(("Failed.\n"));
return retVal;
}
*mode = (GT_PIRL_FC_DEASSERT)data;
DBG_INFO(("OK.\n"));
return GT_OK;
}
/*******************************************************************************
* gpirlGetIngressRateResource
*
* DESCRIPTION:
* This routine gets Ingress Rate Limiting Resources assigned to the port.
* This vector is used to attach specific counter resources to the physical
* port. And the same counter resource can be attached to more than one port.
*
* INPUTS:
* port - logical port number
*
* OUTPUTS:
* resVec - resource vector (bit 11:0, since there is 12 resources)
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gpirlGetIngressRateResource
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
OUT GT_U32 *resVec
)
{
GT_STATUS retVal; /* Functions return value. */
GT_U8 hwPort; /* Physical port. */
GT_U16 data;
DBG_INFO(("grcGetIngressRateResource Called.\n"));
hwPort = GT_LPORT_2_PORT(port);
/* check if the given Switch supports this feature. */
if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
{
DBG_INFO(("GT_NOT_SUPPORTED\n"));
return GT_NOT_SUPPORTED;
}
/* Get the resource vector. */
retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,0,12,&data);
if(retVal != GT_OK)
{
DBG_INFO(("Failed.\n"));
return retVal;
}
*resVec = (GT_U32)data;
DBG_INFO(("OK.\n"));
return GT_OK;
}
/*******************************************************************************
* gpirlSetCurTimeUpInt
*
* DESCRIPTION:
* This function sets the current time update interval.
* Please contact FAE for detailed information.
*
* INPUTS:
* upInt - updata interval (0 ~ 7)
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_BAD_PARAM - if invalid parameter is given
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gpirlSetCurTimeUpInt
(
IN GT_QD_DEV *dev,
IN GT_U32 upInt
)
{
GT_STATUS retVal; /* Functions return value */
GT_PIRL_OPERATION op;
GT_PIRL_OP_DATA opData;
/* check if device supports this feature */
if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
{
DBG_INFO(("GT_NOT_SUPPORTED\n"));
return GT_NOT_SUPPORTED;
}
if (upInt > 0x7)
return GT_BAD_PARAM;
op = PIRL_READ_RESOURCE;
opData.irlUnit = 0xF;
opData.irlReg = 1;
opData.irlData = 0;
retVal = pirlOperationPerform(dev, op, &opData);
if (retVal != GT_OK)
{
DBG_INFO(("PIRL OP Failed.\n"));
return retVal;
}
op = PIRL_WRITE_RESOURCE;
opData.irlData = (opData.irlData & 0xFFF8) | (GT_U16)upInt;
retVal = pirlOperationPerform(dev, op, &opData);
if (retVal != GT_OK)
{
DBG_INFO(("PIRL OP Failed.\n"));
return retVal;
}
return GT_OK;
}
/****************************************************************************/
/* Internal functions. */
/****************************************************************************/
/*******************************************************************************
* gpirlInitialize
*
* DESCRIPTION:
* This routine initializes PIRL Resources.
*
* INPUTS:
* None
*
* OUTPUTS:
* None
*
* RETURNS:
* None
*
* COMMENTS:
* None
*
*******************************************************************************/
GT_STATUS gpirlInitialize
(
IN GT_QD_DEV *dev
)
{
GT_STATUS retVal;
GT_LPORT port;
GT_U8 hwPort; /* Physical port. */
/* reset port's ingress resource bit */
for(port=0; port<dev->numOfPorts; port++)
{
hwPort = GT_LPORT_2_PORT(port);
/* Set the resource vector. */
retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,0,12,0);
if(retVal != GT_OK)
{
DBG_INFO(("Failed.\n"));
return retVal;
}
}
retVal = pirlInitialize(dev);
if(retVal != GT_OK)
{
DBG_INFO(("Failed.\n"));
return retVal;
}
return GT_OK;
}
/*******************************************************************************
* statsOperationPerform
*
* DESCRIPTION:
* This function accesses Ingress Rate Command Register and Data Register.
*
* INPUTS:
* pirlOp - The stats operation bits to be written into the stats
* operation register.
* port - port number
* counter - counter to be read if it's read operation
*
* OUTPUTS:
* pirlData - points to the data storage where the MIB counter will be saved.
*
* RETURNS:
* GT_OK on success,
* GT_FAIL otherwise.
*
* COMMENTS:
*
*******************************************************************************/
static GT_STATUS pirlOperationPerform
(
IN GT_QD_DEV *dev,
IN GT_PIRL_OPERATION pirlOp,
INOUT GT_PIRL_OP_DATA *opData
)
{
GT_STATUS retVal; /* Functions return value */
GT_U16 data; /* temporary Data storage */
gtSemTake(dev,dev->pirlRegsSem,OS_WAIT_FOREVER);
/* Wait until the pirl in ready. */
data = 1;
while(data == 1)
{
retVal = hwGetGlobal2RegField(dev,QD_REG_INGRESS_RATE_COMMAND,15,1,&data);
if(retVal != GT_OK)
{
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
}
}
/* Set the PIRL Operation register */
switch (pirlOp)
{
case PIRL_INIT_ALL_RESOURCE:
data = (1 << 15) | (PIRL_INIT_ALL_RESOURCE << 12);
retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
if(retVal != GT_OK)
{
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
}
break;
case PIRL_INIT_RESOURCE:
data = (GT_U16)((1 << 15) | (PIRL_INIT_RESOURCE << 12) |
((opData->irlUnit&0xF)<< 4));
retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
if(retVal != GT_OK)
{
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
}
break;
case PIRL_WRITE_RESOURCE:
data = (GT_U16)opData->irlData;
retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_DATA,data);
if(retVal != GT_OK)
{
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
}
data = (GT_U16)((1 << 15) | (PIRL_WRITE_RESOURCE << 12) |
((opData->irlUnit&0xF) << 4) | (opData->irlReg & 0xF));
retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
if(retVal != GT_OK)
{
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
}
break;
case PIRL_READ_RESOURCE:
data = (GT_U16)((1 << 15) | (PIRL_READ_RESOURCE << 12) |
((opData->irlUnit&0xF) << 4) | (opData->irlReg & 0xF));
retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
if(retVal != GT_OK)
{
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
}
data = 1;
while(data == 1)
{
retVal = hwGetGlobal2RegField(dev,QD_REG_INGRESS_RATE_COMMAND,15,1,&data);
if(retVal != GT_OK)
{
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
}
}
retVal = hwReadGlobal2Reg(dev,QD_REG_INGRESS_RATE_DATA,&data);
opData->irlData = (GT_U32)data;
if(retVal != GT_OK)
{
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
}
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
default:
gtSemGive(dev,dev->pirlRegsSem);
return GT_FAIL;
}
/* Wait until the pirl in ready. */
data = 1;
while(data == 1)
{
retVal = hwGetGlobal2RegField(dev,QD_REG_INGRESS_RATE_COMMAND,15,1,&data);
if(retVal != GT_OK)
{
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
}
}
gtSemGive(dev,dev->pirlRegsSem);
return retVal;
}
/*
* Initialize all PIRL resources to the inital state.
*/
static GT_STATUS pirlInitialize
(
IN GT_QD_DEV *dev
)
{
GT_STATUS retVal; /* Functions return value */
GT_PIRL_OPERATION op;
op = PIRL_INIT_ALL_RESOURCE;
retVal = pirlOperationPerform(dev, op, NULL);
if (retVal != GT_OK)
{
DBG_INFO(("PIRL OP Failed.\n"));
return retVal;
}
retVal = gpirlSetCurTimeUpInt(dev,7);
if (retVal != GT_OK)
{
DBG_INFO(("PIRL OP Failed.\n"));
}
return retVal;
}
/*
* Initialize the selected PIRL resource to the inital state.
* This function initializes only the BSM structure for the IRL Unit.
*/
static GT_STATUS pirlInitIRLUnit
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit
)
{
GT_STATUS retVal; /* Functions return value */
GT_PIRL_OPERATION op;
GT_PIRL_OP_DATA opData;
op = PIRL_INIT_RESOURCE;
opData.irlUnit = irlUnit;
retVal = pirlOperationPerform(dev, op, &opData);
if (retVal != GT_OK)
{
DBG_INFO(("PIRL OP Failed.\n"));
return retVal;
}
return retVal;
}
/*
* convert PIRL Data structure to PIRL Resource structure.
* if PIRL Data is not valid, return GT_BAD_PARARM;
*/
static GT_STATUS pirlDataToResource
(
IN GT_QD_DEV *dev,
IN GT_PIRL_DATA *pirlData,
OUT GT_PIRL_RESOURCE *res
)
{
GT_U16 typeMask;
switch(pirlData->accountQConf)
{
case GT_FALSE:
case GT_TRUE:
res->accountQConf = pirlData->accountQConf;
break;
default:
return GT_BAD_PARAM;
}
switch(pirlData->accountFiltered)
{
case GT_FALSE:
case GT_TRUE:
res->accountFiltered = pirlData->accountFiltered;
break;
default:
return GT_BAD_PARAM;
}
switch(pirlData->ebsLimitAction)
{
case ESB_LIMIT_ACTION_DROP:
case ESB_LIMIT_ACTION_FC:
res->ebsLimitAction = pirlData->ebsLimitAction;
break;
default:
return GT_BAD_PARAM;
}
if(pirlData->customSetup.isValid == GT_TRUE)
{
res->ebsLimit = pirlData->customSetup.ebsLimit;
res->cbsLimit = pirlData->customSetup.cbsLimit;
res->bktIncrement = pirlData->customSetup.bktIncrement;
res->bktRateFactor = pirlData->customSetup.bktRateFactor;
}
else
{
if(pirlData->ingressRate == 0)
return GT_BAD_PARAM;
if(pirlData->ingressRate < 1000) /* less than 1Mbps */
{
/* it should be divided by 64 */
if(pirlData->ingressRate % 64)
return GT_BAD_PARAM;
res->bktRateFactor = pirlData->ingressRate/64;
}
else if(pirlData->ingressRate <= 100000) /* less than or equal to 100Mbps */
{
/* it should be divided by 1000 */
if(pirlData->ingressRate % 1000)
return GT_BAD_PARAM;
res->bktRateFactor = pirlData->ingressRate/64 + ((pirlData->ingressRate % 64)?1:0);
}
else if(pirlData->ingressRate <= 200000) /* less than or equal to 200Mbps */
{
/* it should be divided by 10000 */
if(pirlData->ingressRate % 10000)
return GT_BAD_PARAM;
res->bktRateFactor = pirlData->ingressRate/64 + ((pirlData->ingressRate % 64)?1:0);
}
else
return GT_BAD_PARAM;
res->ebsLimit = RECOMMENDED_ESB_LIMIT(dev, pirlData->ingressRate);
res->cbsLimit = RECOMMENDED_CBS_LIMIT(dev, pirlData->ingressRate);
res->bktIncrement = RECOMMENDED_BUCKET_INCREMENT(dev, pirlData->ingressRate);
}
switch(pirlData->bktRateType)
{
case BUCKET_TYPE_TRAFFIC_BASED:
res->bktRateType = pirlData->bktRateType;
if (IS_IN_DEV_GROUP(dev,DEV_RESTRICTED_PIRL_RESOURCE))
{
typeMask = 0xF;
}
else
{
typeMask = 0x7F;
}
if (pirlData->bktTypeMask > typeMask)
{
return GT_BAD_PARAM;
}
else
{
res->bktTypeMask = pirlData->bktTypeMask;
}
break;
case BUCKET_TYPE_RATE_BASED:
if (IS_IN_DEV_GROUP(dev,DEV_RESTRICTED_PIRL_RESOURCE))
return GT_BAD_PARAM;
res->bktRateType = pirlData->bktRateType;
res->bktTypeMask = 0;
break;
default:
return GT_BAD_PARAM;
}
switch(pirlData->byteTobeCounted)
{
case GT_PIRL_COUNT_ALL_LAYER1:
res->byteTobeCounted = 1;
break;
case GT_PIRL_COUNT_ALL_LAYER2:
res->byteTobeCounted = 2;
break;
case GT_PIRL_COUNT_ALL_LAYER3:
res->byteTobeCounted = 6;
break;
default:
return GT_BAD_PARAM;
}
return GT_OK;
}
/*
* convert PIRL Resource structure to PIRL Data structure.
*/
static GT_STATUS pirlResourceToData
(
IN GT_QD_DEV *dev,
IN GT_PIRL_RESOURCE *res,
OUT GT_PIRL_DATA *pirlData
)
{
GT_U32 rate;
GT_U32 factor;
pirlData->accountQConf = res->accountQConf;
pirlData->accountFiltered = res->accountFiltered;
pirlData->ebsLimitAction = res->ebsLimitAction;
pirlData->customSetup.isValid = GT_FALSE;
FACTOR_FROM_BUCKET_INCREMENT(dev,res->bktIncrement,factor);
rate = res->bktRateFactor * factor;
if(rate == 0)
{
pirlData->ingressRate = 0;
pirlData->customSetup.isValid = GT_TRUE;
pirlData->customSetup.ebsLimit = res->ebsLimit;
pirlData->customSetup.cbsLimit = res->cbsLimit;
pirlData->customSetup.bktIncrement = res->bktIncrement;
pirlData->customSetup.bktRateFactor = res->bktRateFactor;
}
else if(rate < 1000)
{
pirlData->ingressRate = rate;
}
else if(rate < 100000)
{
pirlData->ingressRate = rate - (rate % 1000);
}
else
{
pirlData->ingressRate = rate - (rate % 10000);
}
pirlData->bktRateType = res->bktRateType;
pirlData->bktTypeMask = res->bktTypeMask;
switch(res->byteTobeCounted)
{
case 1:
pirlData->byteTobeCounted = GT_PIRL_COUNT_ALL_LAYER1;
break;
case 2:
pirlData->byteTobeCounted = GT_PIRL_COUNT_ALL_LAYER2;
break;
case 6:
pirlData->byteTobeCounted = GT_PIRL_COUNT_ALL_LAYER3;
break;
default:
return GT_BAD_PARAM;
}
return GT_OK;
}
/*******************************************************************************
* pirlWriteResource
*
* DESCRIPTION:
* This function writes IRL Resource to BCM (Bucket Configuration Memory)
*
* INPUTS:
* irlUnit - resource unit to be accessed
* res - IRL Resource data
*
* OUTPUTS:
* Nont.
*
* RETURNS:
* GT_OK on success,
* GT_FAIL otherwise.
*
* COMMENTS:
*
*******************************************************************************/
static GT_STATUS pirlWriteResource
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
IN GT_PIRL_RESOURCE *res
)
{
GT_STATUS retVal; /* Functions return value */
GT_U16 data[8]; /* temporary Data storage */
GT_PIRL_OPERATION op;
GT_PIRL_OP_DATA opData;
int i;
op = PIRL_WRITE_RESOURCE;
/* reg0 data */
data[0] = (GT_U16)((res->bktRateType << 15) | /* Bit[15] : Bucket Rate Type */
(res->bktTypeMask << 4 ) | /* Bit[14:4] : Traffic Type */
res->byteTobeCounted ); /* Bit[3:0] : Bytes to be counted */
/* reg1 data */
data[1] = (GT_U16)res->bktIncrement; /* Bit[11:0] : Bucket Increment */
/* reg2 data */
data[2] = (GT_U16)res->bktRateFactor; /* Bit[15:0] : Bucket Rate Factor */
/* reg3 data */
data[3] = (GT_U16)(res->cbsLimit & 0xFFF) << 4; /* Bit[15:4] : CBS Limit[11:0] */
/* reg4 data */
data[4] = (GT_U16)(res->cbsLimit >> 12); /* Bit[11:0] : CBS Limit[23:12] */
/* reg5 data */
data[5] = (GT_U16)(res->ebsLimit & 0xFFFF); /* Bit[15:0] : EBS Limit[15:0] */
/* reg6 data */
data[6] = (GT_U16)((res->ebsLimit >> 16) | /* Bit[7:0] : EBS Limit[23:16] */
(res->ebsLimitAction << 12) | /* Bit[12] : EBS Limit Action */
(res->accountFiltered << 14)| /* Bit[14] : Account Filtered */
(res->accountQConf << 15)); /* Bit[15] : Account QConf */
/* reg7 data */
data[7] = 0; /* Reserved */
for(i=0; i<8; i++)
{
opData.irlUnit = irlUnit;
opData.irlReg = i;
opData.irlData = data[i];
retVal = pirlOperationPerform(dev, op, &opData);
if (retVal != GT_OK)
{
DBG_INFO(("PIRL OP Failed.\n"));
return retVal;
}
}
return GT_OK;
}
/*******************************************************************************
* pirlReadResource
*
* DESCRIPTION:
* This function reads IRL Resource from BCM (Bucket Configuration Memory)
*
* INPUTS:
* irlUnit - resource unit to be accessed
*
* OUTPUTS:
* res - IRL Resource data
*
* RETURNS:
* GT_OK on success,
* GT_FAIL otherwise.
*
* COMMENTS:
*
*******************************************************************************/
static GT_STATUS pirlReadResource
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
OUT GT_PIRL_RESOURCE *res
)
{
GT_STATUS retVal; /* Functions return value */
GT_U16 data[8]; /* temporary Data storage */
GT_PIRL_OPERATION op;
GT_PIRL_OP_DATA opData;
int i;
op = PIRL_READ_RESOURCE;
for(i=0; i<8; i++)
{
opData.irlUnit = irlUnit;
opData.irlReg = i;
opData.irlData = 0;
retVal = pirlOperationPerform(dev, op, &opData);
if (retVal != GT_OK)
{
DBG_INFO(("PIRL OP Failed.\n"));
return retVal;
}
data[i] = (GT_U16)opData.irlData;
}
/* reg0 data */
res->bktRateType = (data[0] >> 15) & 0x1;
res->bktTypeMask = (data[0] >> 4) & 0x7F;
res->byteTobeCounted = data[0] & 0xF;
/* reg1 data */
res->bktIncrement = data[1] & 0xFFF;
/* reg2 data */
res->bktRateFactor = data[2] & 0xFFFF;
/* reg3,4 data */
res->cbsLimit = ((data[3] >> 4) & 0xFFF) | ((data[4] & 0xFFF) << 12);
/* reg5,6 data */
res->ebsLimit = data[5] | ((data[6] & 0xFF) << 16);
/* reg6 data */
res->ebsLimitAction = (data[6] >> 12) & 0x1;
res->accountFiltered = (data[6] >> 14) & 0x1;
res->accountQConf = (data[6] >> 15) & 0x1;
return GT_OK;
}
/*******************************************************************************
* pirlSetPortVec
*
* DESCRIPTION:
* This routine sets port list that share the bucket and resets ports that
* do not share the bucket.
*
* INPUTS:
* irlUnit - bucket to be used.
* portVec - the list of ports that share the bucket.
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
*
*******************************************************************************/
static GT_STATUS pirlSetPortVec
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
IN GT_U32 portVec
)
{
GT_STATUS retVal; /* Functions return value. */
GT_LPORT port;
GT_U8 hwPort; /* Physical port. */
GT_U16 data;
for(port=0; port<dev->numOfPorts; port++)
{
if(GT_IS_PORT_SET(portVec,port))
data = 1;
else
data = 0;
hwPort = GT_LPORT_2_PORT(port);
/* Set the resource vector. */
retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,(GT_U8)irlUnit,1,data);
if(retVal != GT_OK)
{
DBG_INFO(("Failed.\n"));
return retVal;
}
}
DBG_INFO(("OK.\n"));
return GT_OK;
}
/*******************************************************************************
* pirlGetPortVec
*
* DESCRIPTION:
* This routine gets port list that share the bucket.
*
* INPUTS:
* irlUnit - bucket to be used.
*
* OUTPUTS:
* portVec - the list of ports that share the bucket.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
*
*******************************************************************************/
static GT_STATUS pirlGetPortVec
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
OUT GT_U32 *portVec
)
{
GT_STATUS retVal; /* Functions return value. */
GT_LPORT port;
GT_U8 hwPort; /* Physical port. */
GT_U16 data;
*portVec = 0;
for(port=0; port<dev->numOfPorts; port++)
{
hwPort = GT_LPORT_2_PORT(port);
/* Set the resource vector. */
retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,(GT_U8)irlUnit,1,&data);
if(retVal != GT_OK)
{
DBG_INFO(("Failed.\n"));
return retVal;
}
if(data == 1)
*portVec |= (1 << port);
}
DBG_INFO(("OK.\n"));
return GT_OK;
}
/*******************************************************************************
* pirlSetFcMode
*
* DESCRIPTION:
* This routine gets Port Ingress Rate Limit Flow Control mode.
* When EBSLimitAction is programmed to generate a flow control message,
* the deassertion of flow control is controlled by this mode.
* GT_PIRL_FC_DEASSERT_EMPTY:
* De-assert when the ingress rate resource has become empty
* GT_PIRL_FC_DEASSERT_CBS_LIMIT
* De-assert when the ingress rate resource has enough room as
* specified by the CBSLimit.
* Please refer to GT_PIRL_RESOURCE structure for EBSLimitAction and
* CBSLimit.
*
* INPUTS:
* port - logical port number
* mode - GT_PIRL_FC_DEASSERT enum type
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*
*******************************************************************************/
static GT_STATUS pirlSetFcMode
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_PIRL_FC_DEASSERT mode
)
{
GT_U16 data;
GT_STATUS retVal; /* Functions return value. */
GT_U8 hwPort; /* Physical port. */
DBG_INFO(("pirlSetFcMode Called.\n"));
hwPort = GT_LPORT_2_PORT(port);
data = (GT_U16) mode;
/* Set the PirlFcMode. */
retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,12,1,data);
if(retVal != GT_OK)
{
DBG_INFO(("Failed.\n"));
return retVal;
}
DBG_INFO(("OK.\n"));
return GT_OK;
}
#define PIRL_DEBUG
#ifdef PIRL_DEBUG
/*******************************************************************************
* pirlDumpResource
*
* DESCRIPTION:
* This function dumps IRL Resource register values.
*
* INPUTS:
* irlUnit - resource unit to be accessed
* dataLen - data size.
*
* OUTPUTS:
* data - IRL Resource data
*
* RETURNS:
* GT_OK on success,
* GT_FAIL otherwise.
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS pirlDumpResource
(
IN GT_QD_DEV *dev,
IN GT_U32 irlUnit,
IN GT_U32 dataLen,
OUT GT_U16 *data
)
{
GT_STATUS retVal; /* Functions return value */
GT_PIRL_OPERATION op;
GT_PIRL_OP_DATA opData;
GT_U32 i;
/* check if device supports this feature */
if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
{
DBG_INFO(("GT_NOT_SUPPORTED\n"));
return GT_NOT_SUPPORTED;
}
op = PIRL_READ_RESOURCE;
for(i=0; i<dataLen; i++)
{
opData.irlUnit = irlUnit;
opData.irlReg = i;
opData.irlData = 0;
retVal = pirlOperationPerform(dev, op, &opData);
if (retVal != GT_OK)
{
DBG_INFO(("PIRL OP Failed.\n"));
return retVal;
}
data[i] = (GT_U16)opData.irlData;
}
return GT_OK;
}
#endif /* PIRL_DEBUG */