/******************************************************************************* * gsysSetQoSWeight * * DESCRIPTION: * Programmable Round Robin Weights. * Each port has 4/8 output Queues. Queue 3/7 has the highest priority and * Queue 0 has the lowest priority. When a scheduling mode of port is * configured as Weighted Round Robin queuing mode, the access sequece of the * Queue is 3,2,3,1,3,2,3,0,3,2,3,1,3,2,3 by default. * (Queue is 7,6,5,7,1,6,7,4 by default. That is after 6390.) * This sequence can be configured with this API. * * INPUTS: * weight - access sequence of the queue * * OUTPUTS: * None. * * RETURNS: * GT_OK - on success * GT_FAIL - on error * GT_NOT_SUPPORTED - if current device does not support this feature. * * COMMENTS: * None * *******************************************************************************/ GT_STATUS gsysSetQoSWeight ( IN GT_QD_DEV *dev, IN GT_QoS_WEIGHT *weight ) { GT_STATUS retVal; /* Functions return value. */ GT_U16 data; GT_U32 len, i; int length_loc, entry_num; DBG_INFO(("gsysSetQoSWeight Called.\n")); /* Check if Switch supports this feature. */ if (!IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT)) { DBG_INFO(("GT_NOT_SUPPORTED\n")); return GT_NOT_SUPPORTED; } if (IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT_1)) { length_loc = 0x40; entry_num = 2; } else { length_loc = 0x20; entry_num = 4; } if (weight->len > 128) { DBG_INFO(("GT_BAD_PARAM\n")); return GT_BAD_PARAM; } gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER); len = weight->len/entry_num; /* program QoS Weight Table, 4/2 sequences at a time */ for(i=0; i<len; i++) { /* Wait until the QoS Weight Table is ready. */ #ifdef GT_RMGMT_ACCESS { HW_DEV_REG_ACCESS regAccess; regAccess.entries = 2; regAccess.rw_reg_list[0].cmd = HW_REG_WAIT_TILL_0; regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS); regAccess.rw_reg_list[0].reg = QD_REG_QOS_WEIGHT; regAccess.rw_reg_list[0].data = 15; regAccess.rw_reg_list[1].cmd = HW_REG_WRITE; regAccess.rw_reg_list[1].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS); regAccess.rw_reg_list[1].reg = QD_REG_QOS_WEIGHT; if (IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT_1)) { data = (GT_U16)((1 << 15) | (i << 8) | (weight->queue[i*2] & 0x7) | ((weight->queue[i*2+1] & 0x7) << 4); } else { data = (GT_U16)((1 << 15) | (i << 8) | (weight->queue[i*4] & 0x3) | ((weight->queue[i*4+1] & 0x3) << 2) | ((weight->queue[i*4+2] & 0x3) << 4) | ((weight->queue[i*4+3] & 0x3) << 6)); } regAccess.rw_reg_list[1].data = data; retVal = hwAccessMultiRegs(dev, ®Access); if(retVal != GT_OK) { gtSemGive(dev,dev->tblRegsSem); return retVal; } } #else data = 1; while(data == 1) { retVal = hwGetGlobal2RegField(dev,QD_REG_QOS_WEIGHT,15,1,&data); if(retVal != GT_OK) { gtSemGive(dev,dev->tblRegsSem); return retVal; } } if (IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT_1)) { data = (GT_U16)((1 << 15) | (i << 8) | (weight->queue[i*2] & 0x7) | ((weight->queue[i*2+1] & 0x7) << 4)); } else { data = (GT_U16)((1 << 15) | (i << 8) | (weight->queue[i*4] & 0x3) | ((weight->queue[i*4+1] & 0x3) << 2) | ((weight->queue[i*4+2] & 0x3) << 4) | ((weight->queue[i*4+3] & 0x3) << 6)); } retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data); if(retVal != GT_OK) { DBG_INFO(("Failed.\n")); gtSemGive(dev,dev->tblRegsSem); return retVal; } #endif }
/******************************************************************************* * statsCapture * * DESCRIPTION: * This function is used to capture all counters of a port. * * INPUTS: * port - port number * * OUTPUTS: * None. * * RETURNS: * GT_OK on success, * GT_FAIL otherwise. * * COMMENTS: * If Semaphore is used, Semaphore should be acquired before this function call. *******************************************************************************/ static GT_STATUS statsCapture ( IN GT_QD_DEV *dev, IN GT_U8 port ) { GT_STATUS retVal; /* Functions return value. */ GT_U16 data, histoData;/* Data to be set into the */ /* register. */ GT_U16 portNum; if (IS_IN_DEV_GROUP(dev,DEV_RMON_PORT_BITS)) { portNum = (port + 1) << 5; } else { portNum = (GT_U16)port; } /* Get the Histogram mode bit. */ retVal = hwReadGlobalReg(dev,QD_REG_STATS_OPERATION,&histoData); if(retVal != GT_OK) { return retVal; } histoData &= 0xC00; #ifdef GT_RMGMT_ACCESS { HW_DEV_REG_ACCESS regAccess; regAccess.entries = 1; regAccess.rw_reg_list[0].cmd = HW_REG_WAIT_TILL_0; regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS); regAccess.rw_reg_list[0].reg = QD_REG_STATS_OPERATION; regAccess.rw_reg_list[0].data = 15; retVal = hwAccessMultiRegs(dev, ®Access); if(retVal != GT_OK) { return retVal; } } #else data = 1; while(data == 1) { retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data); if(retVal != GT_OK) { return retVal; } } #endif data = (1 << 15) | (GT_STATS_CAPTURE_PORT << 12) | portNum | histoData; retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data); if(retVal != GT_OK) { return retVal; } return GT_OK; }
/******************************************************************************* * statsReadRealtimeCounter * * DESCRIPTION: * This function is used to read a realtime counter. * * INPUTS: * port - port to be accessed * counter - counter to be read if it's read operation * * OUTPUTS: * statsData - points to the data storage where the MIB counter will be saved. * * RETURNS: * GT_OK on success, * GT_FAIL otherwise. * * COMMENTS: * If Semaphore is used, Semaphore should be acquired before this function call. *******************************************************************************/ static GT_STATUS statsReadRealtimeCounter ( IN GT_QD_DEV *dev, IN GT_U8 port, IN GT_U32 counter, OUT GT_U32 *statsData ) { GT_STATUS retVal; /* Functions return value. */ GT_U16 data, histoData;/* Data to be set into the register. */ GT_U16 counter3_2; /* Counter Register Bytes 3 & 2 */ GT_U16 counter1_0; /* Counter Register Bytes 1 & 0 */ /* Get the Histogram mode bit. */ retVal = hwReadGlobalReg(dev,QD_REG_STATS_OPERATION,&histoData); if(retVal != GT_OK) { return retVal; } histoData &= 0xC00; #ifdef GT_RMGMT_ACCESS { HW_DEV_REG_ACCESS regAccess; regAccess.entries = 1; regAccess.rw_reg_list[0].cmd = HW_REG_WAIT_TILL_0; regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS); regAccess.rw_reg_list[0].reg = QD_REG_STATS_OPERATION; regAccess.rw_reg_list[0].data = 15; retVal = hwAccessMultiRegs(dev, ®Access); if(retVal != GT_OK) { return retVal; } } #else data = 1; while(data == 1) { retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data); if(retVal != GT_OK) { return retVal; } } #endif data = (GT_U16)((1 << 15) | (GT_STATS_READ_COUNTER << 12) | ((port+1) << 5) | counter | histoData); retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data); if(retVal != GT_OK) { return retVal; } #ifdef GT_RMGMT_ACCESS { HW_DEV_REG_ACCESS regAccess; regAccess.entries = 1; regAccess.rw_reg_list[0].cmd = HW_REG_WAIT_TILL_0; regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS); regAccess.rw_reg_list[0].reg = QD_REG_STATS_OPERATION; regAccess.rw_reg_list[0].data = 15; retVal = hwAccessMultiRegs(dev, ®Access); if(retVal != GT_OK) { return retVal; } } #else data = 1; while(data == 1) { retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data); if(retVal != GT_OK) { return retVal; } } #endif retVal = hwReadGlobalReg(dev,QD_REG_STATS_COUNTER3_2,&counter3_2); if(retVal != GT_OK) { return retVal; } retVal = hwReadGlobalReg(dev,QD_REG_STATS_COUNTER1_0,&counter1_0); if(retVal != GT_OK) { return retVal; } *statsData = (counter3_2 << 16) | counter1_0; return GT_OK; }
static GT_STATUS statsOperationPerform ( IN GT_QD_DEV *dev, IN GT_STATS_OPERATION statsOp, IN GT_U8 port, IN GT_STATS_COUNTERS counter, OUT GT_VOID *statsData ) { GT_STATUS retVal; /* Functions return value. */ GT_U16 data,histoData; /* Data to be set into the */ /* register. */ GT_U32 statsCounter; GT_U32 lastCounter; GT_U16 portNum; gtSemTake(dev,dev->statsRegsSem,OS_WAIT_FOREVER); if (!((IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH)) || (IS_IN_DEV_GROUP(dev,DEV_RMON_REALTIME_SUPPORT)))) { if (IS_IN_DEV_GROUP(dev,DEV_MELODY_SWITCH)) lastCounter = (GT_U32)STATS2_Late; else lastCounter = (GT_U32)STATS_OutDiscards; } else { lastCounter = (GT_U32)STATS2_Late; } if (IS_IN_DEV_GROUP(dev,DEV_RMON_PORT_BITS)) { portNum = (port + 1) << 5; } else { portNum = (GT_U16)port; } /* Wait until the stats in ready. */ #ifdef GT_RMGMT_ACCESS { HW_DEV_REG_ACCESS regAccess; regAccess.entries = 2; regAccess.rw_reg_list[0].cmd = HW_REG_WAIT_TILL_0; regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS); regAccess.rw_reg_list[0].reg = QD_REG_STATS_OPERATION; regAccess.rw_reg_list[0].data = 15; regAccess.rw_reg_list[1].cmd = HW_REG_READ; regAccess.rw_reg_list[1].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS); regAccess.rw_reg_list[1].reg = QD_REG_STATS_OPERATION; regAccess.rw_reg_list[1].data = 0; retVal = hwAccessMultiRegs(dev, ®Access); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } histoData = qdLong2Short(regAccess.rw_reg_list[1].data); } #else data = 1; while(data == 1) { retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } } /* Get the Histogram mode bit. */ retVal = hwReadGlobalReg(dev,QD_REG_STATS_OPERATION,&histoData); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } #endif histoData &= 0xC00; /* Set the STAT Operation register */ switch (statsOp) { case STATS_FLUSH_ALL: data = (1 << 15) | (GT_STATS_FLUSH_ALL << 12) | histoData; retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data); gtSemGive(dev,dev->statsRegsSem); return retVal; case STATS_FLUSH_PORT: data = (1 << 15) | (GT_STATS_FLUSH_PORT << 12) | portNum | histoData; retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data); gtSemGive(dev,dev->statsRegsSem); return retVal; case STATS_READ_COUNTER: retVal = statsCapture(dev,port); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } retVal = statsReadCounter(dev,counter,(GT_U32*)statsData); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } break; case STATS_READ_REALTIME_COUNTER: retVal = statsReadRealtimeCounter(dev,port,counter,(GT_U32*)statsData); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } break; case STATS_READ_ALL: retVal = statsCapture(dev,port); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } for(statsCounter=0; statsCounter<=lastCounter; statsCounter++) { retVal = statsReadCounter(dev,statsCounter,((GT_U32*)statsData + statsCounter)); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } } break; default: gtSemGive(dev,dev->statsRegsSem); return GT_FAIL; } gtSemGive(dev,dev->statsRegsSem); return GT_OK; }
/******************************************************************************* * gprtGetPortCtr2 * * DESCRIPTION: * This routine gets the port InDiscards, InFiltered, and OutFiltered counters. * * INPUTS: * port - the logical port number. * * OUTPUTS: * ctr - the counters value. * * RETURNS: * GT_OK - on success * GT_FAIL - on error * * COMMENTS: * * * GalTis: * *******************************************************************************/ GT_STATUS gprtGetPortCtr2 ( IN GT_QD_DEV *dev, IN GT_LPORT port, OUT GT_PORT_STAT2 *ctr ) { #ifndef GT_RMGMT_ACCESS GT_U16 count; /* counters current value */ #endif GT_U8 hwPort; /* physical port number */ DBG_INFO(("gprtGetPortCtr2 Called.\n")); if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY)) { DBG_INFO(("GT_NOT_SUPPORTED\n")); return GT_NOT_SUPPORTED; } if(ctr == NULL) { DBG_INFO(("Failed.\n")); return GT_BAD_PARAM; } /* translate logical port to physical port */ hwPort = GT_LPORT_2_PORT(port); #ifdef GT_RMGMT_ACCESS { HW_DEV_REG_ACCESS regAccess; regAccess.entries = 4; regAccess.rw_reg_list[0].cmd = HW_REG_READ; regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, hwPort, PORT_ACCESS); regAccess.rw_reg_list[0].reg = QD_REG_INDISCARD_LO_COUNTER; regAccess.rw_reg_list[0].data = 0; regAccess.rw_reg_list[1].cmd = HW_REG_READ; regAccess.rw_reg_list[1].addr = CALC_SMI_DEV_ADDR(dev, hwPort, PORT_ACCESS); regAccess.rw_reg_list[1].reg = QD_REG_INDISCARD_HI_COUNTER; regAccess.rw_reg_list[1].data = 0; regAccess.rw_reg_list[2].cmd = HW_REG_READ; regAccess.rw_reg_list[2].addr = CALC_SMI_DEV_ADDR(dev, hwPort, PORT_ACCESS); regAccess.rw_reg_list[2].reg = QD_REG_INFILTERED_COUNTER; regAccess.rw_reg_list[2].data = 0; regAccess.rw_reg_list[3].cmd = HW_REG_READ; regAccess.rw_reg_list[3].addr = CALC_SMI_DEV_ADDR(dev, hwPort, PORT_ACCESS); regAccess.rw_reg_list[3].reg = QD_REG_OUTFILTERED_COUNTER; regAccess.rw_reg_list[3].data = 0; if(hwAccessMultiRegs(dev, ®Access) != GT_OK) { return GT_FAIL; } ctr->inDiscardLo = regAccess.rw_reg_list[0].data; ctr->inDiscardHi = regAccess.rw_reg_list[1].data; ctr->inFiltered = regAccess.rw_reg_list[2].data; ctr->outFiltered = regAccess.rw_reg_list[3].data; } #else /* get InDiscard Low counter value */ if(hwReadPortReg(dev,hwPort, QD_REG_INDISCARD_LO_COUNTER, &count) != GT_OK) { DBG_INFO(("Failed (Read inDiscardLo).\n")); return GT_FAIL; } ctr->inDiscardLo = count; /* get InDiscard High counter value */ if(hwReadPortReg(dev,hwPort, QD_REG_INDISCARD_HI_COUNTER, &count) != GT_OK) { DBG_INFO(("Failed (Read inDiscardHi).\n")); return GT_FAIL; } ctr->inDiscardHi = count; /* get InFiltered counter value */ if(hwReadPortReg(dev,hwPort, QD_REG_INFILTERED_COUNTER, &count) != GT_OK) { DBG_INFO(("Failed (Read inFiltered).\n")); return GT_FAIL; } ctr->inFiltered = count; /* get OutFiltered counter value */ if(hwReadPortReg(dev,hwPort, QD_REG_OUTFILTERED_COUNTER, &count) != GT_OK) { DBG_INFO(("Failed (Read outFiltered).\n")); return GT_FAIL; } ctr->outFiltered = count; #endif DBG_INFO(("OK.\n")); return GT_OK; }