bnx2x: congestion management re-organization
The congestion management code has migrated into a common location, allowing all fw writes controlling mf congestion to be made in a single function in the code. This is a semantic change. Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								7e8e02df17
							
						
					
				
			
			
				commit
				
					
						b475d78f46
					
				
			
		
					 5 changed files with 331 additions and 163 deletions
				
			
		| 
						 | 
				
			
			@ -30,6 +30,10 @@
 | 
			
		|||
#if defined(CONFIG_DCB)
 | 
			
		||||
#define BCM_DCBNL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "bnx2x_hsi.h"
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
 | 
			
		||||
#define BCM_CNIC 1
 | 
			
		||||
#include "../cnic_if.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -1336,8 +1340,8 @@ struct bnx2x {
 | 
			
		|||
	struct bnx2x_common	common;
 | 
			
		||||
	struct bnx2x_port	port;
 | 
			
		||||
 | 
			
		||||
	struct cmng_struct_per_port cmng;
 | 
			
		||||
	u32			vn_weight_sum;
 | 
			
		||||
	struct cmng_init	cmng;
 | 
			
		||||
 | 
			
		||||
	u32			mf_config[E1HVN_MAX];
 | 
			
		||||
	u32			mf2_config[E2_FUNC_MAX];
 | 
			
		||||
	u32			path_has_ovlan; /* E3 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -964,6 +964,12 @@ static inline void bnx2x_reuse_rx_data(struct bnx2x_fastpath *fp,
 | 
			
		|||
 | 
			
		||||
/************************* Init ******************************************/
 | 
			
		||||
 | 
			
		||||
/* returns func by VN for current port */
 | 
			
		||||
static inline int func_by_vn(struct bnx2x *bp, int vn)
 | 
			
		||||
{
 | 
			
		||||
	return 2 * vn + BP_PORT(bp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * bnx2x_func_start - init function
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -1419,15 +1425,32 @@ static inline void storm_memset_func_cfg(struct bnx2x *bp,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static inline void storm_memset_cmng(struct bnx2x *bp,
 | 
			
		||||
				struct cmng_struct_per_port *cmng,
 | 
			
		||||
				struct cmng_init *cmng,
 | 
			
		||||
				u8 port)
 | 
			
		||||
{
 | 
			
		||||
	int vn;
 | 
			
		||||
	size_t size = sizeof(struct cmng_struct_per_port);
 | 
			
		||||
 | 
			
		||||
	u32 addr = BAR_XSTRORM_INTMEM +
 | 
			
		||||
			XSTORM_CMNG_PER_PORT_VARS_OFFSET(port);
 | 
			
		||||
 | 
			
		||||
	__storm_memset_struct(bp, addr, size, (u32 *)cmng);
 | 
			
		||||
	__storm_memset_struct(bp, addr, size, (u32 *)&cmng->port);
 | 
			
		||||
 | 
			
		||||
	for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) {
 | 
			
		||||
		int func = func_by_vn(bp, vn);
 | 
			
		||||
 | 
			
		||||
		addr = BAR_XSTRORM_INTMEM +
 | 
			
		||||
		       XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(func);
 | 
			
		||||
		size = sizeof(struct rate_shaping_vars_per_vn);
 | 
			
		||||
		__storm_memset_struct(bp, addr, size,
 | 
			
		||||
				      (u32 *)&cmng->vnic.vnic_max_rate[vn]);
 | 
			
		||||
 | 
			
		||||
		addr = BAR_XSTRORM_INTMEM +
 | 
			
		||||
		       XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(func);
 | 
			
		||||
		size = sizeof(struct fairness_vars_per_vn);
 | 
			
		||||
		__storm_memset_struct(bp, addr, size,
 | 
			
		||||
				      (u32 *)&cmng->vnic.vnic_min_rate[vn]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -1608,11 +1631,6 @@ static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
 | 
			
		|||
 */
 | 
			
		||||
void bnx2x_get_iscsi_info(struct bnx2x *bp);
 | 
			
		||||
#endif
 | 
			
		||||
/* returns func by VN for current port */
 | 
			
		||||
static inline int func_by_vn(struct bnx2x *bp, int vn)
 | 
			
		||||
{
 | 
			
		||||
	return 2 * vn + BP_PORT(bp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * bnx2x_link_sync_notify - send notification to other functions.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4448,6 +4448,65 @@ struct cmng_struct_per_port {
 | 
			
		|||
	struct cmng_flags_per_port flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * a single rate shaping counter. can be used as protocol or vnic counter
 | 
			
		||||
 */
 | 
			
		||||
struct rate_shaping_counter {
 | 
			
		||||
	u32 quota;
 | 
			
		||||
#if defined(__BIG_ENDIAN)
 | 
			
		||||
	u16 __reserved0;
 | 
			
		||||
	u16 rate;
 | 
			
		||||
#elif defined(__LITTLE_ENDIAN)
 | 
			
		||||
	u16 rate;
 | 
			
		||||
	u16 __reserved0;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * per-vnic rate shaping variables
 | 
			
		||||
 */
 | 
			
		||||
struct rate_shaping_vars_per_vn {
 | 
			
		||||
	struct rate_shaping_counter vn_counter;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * per-vnic fairness variables
 | 
			
		||||
 */
 | 
			
		||||
struct fairness_vars_per_vn {
 | 
			
		||||
	u32 cos_credit_delta[MAX_COS_NUMBER];
 | 
			
		||||
	u32 vn_credit_delta;
 | 
			
		||||
	u32 __reserved0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * cmng port init state
 | 
			
		||||
 */
 | 
			
		||||
struct cmng_vnic {
 | 
			
		||||
	struct rate_shaping_vars_per_vn vnic_max_rate[4];
 | 
			
		||||
	struct fairness_vars_per_vn vnic_min_rate[4];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * cmng port init state
 | 
			
		||||
 */
 | 
			
		||||
struct cmng_init {
 | 
			
		||||
	struct cmng_struct_per_port port;
 | 
			
		||||
	struct cmng_vnic vnic;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * driver parameters for congestion management init, all rates are in Mbps
 | 
			
		||||
 */
 | 
			
		||||
struct cmng_init_input {
 | 
			
		||||
	u32 port_rate;
 | 
			
		||||
	u16 vnic_min_rate[4];
 | 
			
		||||
	u16 vnic_max_rate[4];
 | 
			
		||||
	u16 cos_min_rate[MAX_COS_NUMBER];
 | 
			
		||||
	u16 cos_to_pause_mask[MAX_COS_NUMBER];
 | 
			
		||||
	struct cmng_flags_per_port flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Protocol-common command ID for slow path elements
 | 
			
		||||
| 
						 | 
				
			
			@ -4762,16 +4821,6 @@ enum fairness_mode {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * per-vnic fairness variables
 | 
			
		||||
 */
 | 
			
		||||
struct fairness_vars_per_vn {
 | 
			
		||||
	u32 cos_credit_delta[MAX_COS_NUMBER];
 | 
			
		||||
	u32 vn_credit_delta;
 | 
			
		||||
	u32 __reserved0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Priority and cos
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -5139,29 +5188,6 @@ struct protocol_common_spe {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * a single rate shaping counter. can be used as protocol or vnic counter
 | 
			
		||||
 */
 | 
			
		||||
struct rate_shaping_counter {
 | 
			
		||||
	u32 quota;
 | 
			
		||||
#if defined(__BIG_ENDIAN)
 | 
			
		||||
	u16 __reserved0;
 | 
			
		||||
	u16 rate;
 | 
			
		||||
#elif defined(__LITTLE_ENDIAN)
 | 
			
		||||
	u16 rate;
 | 
			
		||||
	u16 __reserved0;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * per-vnic rate shaping variables
 | 
			
		||||
 */
 | 
			
		||||
struct rate_shaping_vars_per_vn {
 | 
			
		||||
	struct rate_shaping_counter vn_counter;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The send queue element
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -241,7 +241,8 @@ static inline void bnx2x_map_q_cos(struct bnx2x *bp, u32 q_num, u32 new_cos)
 | 
			
		|||
			REG_WR(bp, reg_addr, reg_bit_map | q_bit_map);
 | 
			
		||||
 | 
			
		||||
			/* set/clear queue bit in command-queue bit map
 | 
			
		||||
			(E2/E3A0 only, valid COS values are 0/1) */
 | 
			
		||||
			 * (E2/E3A0 only, valid COS values are 0/1)
 | 
			
		||||
			 */
 | 
			
		||||
			if (!(INIT_MODE_FLAGS(bp) & MODE_E3_B0)) {
 | 
			
		||||
				reg_addr = BNX2X_Q_CMDQ_REG_ADDR(pf_q_num);
 | 
			
		||||
				reg_bit_map = REG_RD(bp, reg_addr);
 | 
			
		||||
| 
						 | 
				
			
			@ -277,7 +278,215 @@ static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Returns the index of start or end of a specific block stage in ops array*/
 | 
			
		||||
/* congestion managment port init api description
 | 
			
		||||
 * the api works as follows:
 | 
			
		||||
 * the driver should pass the cmng_init_input struct, the port_init function
 | 
			
		||||
 * will prepare the required internal ram structure which will be passed back
 | 
			
		||||
 * to the driver (cmng_init) that will write it into the internal ram.
 | 
			
		||||
 *
 | 
			
		||||
 * IMPORTANT REMARKS:
 | 
			
		||||
 * 1. the cmng_init struct does not represent the contiguous internal ram
 | 
			
		||||
 *    structure. the driver should use the XSTORM_CMNG_PERPORT_VARS_OFFSET
 | 
			
		||||
 *    offset in order to write the port sub struct and the
 | 
			
		||||
 *    PFID_FROM_PORT_AND_VNIC offset for writing the vnic sub struct (in other
 | 
			
		||||
 *    words - don't use memcpy!).
 | 
			
		||||
 * 2. although the cmng_init struct is filled for the maximal vnic number
 | 
			
		||||
 *    possible, the driver should only write the valid vnics into the internal
 | 
			
		||||
 *    ram according to the appropriate port mode.
 | 
			
		||||
 */
 | 
			
		||||
#define BITS_TO_BYTES(x) ((x)/8)
 | 
			
		||||
 | 
			
		||||
/* CMNG constants, as derived from system spec calculations */
 | 
			
		||||
 | 
			
		||||
/* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */
 | 
			
		||||
#define DEF_MIN_RATE 100
 | 
			
		||||
 | 
			
		||||
/* resolution of the rate shaping timer - 400 usec */
 | 
			
		||||
#define RS_PERIODIC_TIMEOUT_USEC 400
 | 
			
		||||
 | 
			
		||||
/* number of bytes in single QM arbitration cycle -
 | 
			
		||||
 * coefficient for calculating the fairness timer
 | 
			
		||||
 */
 | 
			
		||||
#define QM_ARB_BYTES 160000
 | 
			
		||||
 | 
			
		||||
/* resolution of Min algorithm 1:100 */
 | 
			
		||||
#define MIN_RES 100
 | 
			
		||||
 | 
			
		||||
/* how many bytes above threshold for
 | 
			
		||||
 * the minimal credit of Min algorithm
 | 
			
		||||
 */
 | 
			
		||||
#define MIN_ABOVE_THRESH 32768
 | 
			
		||||
 | 
			
		||||
/* Fairness algorithm integration time coefficient -
 | 
			
		||||
 * for calculating the actual Tfair
 | 
			
		||||
 */
 | 
			
		||||
#define T_FAIR_COEF ((MIN_ABOVE_THRESH + QM_ARB_BYTES) * 8 * MIN_RES)
 | 
			
		||||
 | 
			
		||||
/* Memory of fairness algorithm - 2 cycles */
 | 
			
		||||
#define FAIR_MEM 2
 | 
			
		||||
#define SAFC_TIMEOUT_USEC 52
 | 
			
		||||
 | 
			
		||||
#define SDM_TICKS 4
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static inline void bnx2x_init_max(const struct cmng_init_input *input_data,
 | 
			
		||||
				  u32 r_param, struct cmng_init *ram_data)
 | 
			
		||||
{
 | 
			
		||||
	u32 vnic;
 | 
			
		||||
	struct cmng_vnic *vdata = &ram_data->vnic;
 | 
			
		||||
	struct cmng_struct_per_port *pdata = &ram_data->port;
 | 
			
		||||
	/* rate shaping per-port variables
 | 
			
		||||
	 * 100 micro seconds in SDM ticks = 25
 | 
			
		||||
	 * since each tick is 4 microSeconds
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	pdata->rs_vars.rs_periodic_timeout =
 | 
			
		||||
	RS_PERIODIC_TIMEOUT_USEC / SDM_TICKS;
 | 
			
		||||
 | 
			
		||||
	/* this is the threshold below which no timer arming will occur.
 | 
			
		||||
	 * 1.25 coefficient is for the threshold to be a little bigger
 | 
			
		||||
	 * then the real time to compensate for timer in-accuracy
 | 
			
		||||
	 */
 | 
			
		||||
	pdata->rs_vars.rs_threshold =
 | 
			
		||||
	(5 * RS_PERIODIC_TIMEOUT_USEC * r_param)/4;
 | 
			
		||||
 | 
			
		||||
	/* rate shaping per-vnic variables */
 | 
			
		||||
	for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++) {
 | 
			
		||||
		/* global vnic counter */
 | 
			
		||||
		vdata->vnic_max_rate[vnic].vn_counter.rate =
 | 
			
		||||
		input_data->vnic_max_rate[vnic];
 | 
			
		||||
		/* maximal Mbps for this vnic
 | 
			
		||||
		 * the quota in each timer period - number of bytes
 | 
			
		||||
		 * transmitted in this period
 | 
			
		||||
		 */
 | 
			
		||||
		vdata->vnic_max_rate[vnic].vn_counter.quota =
 | 
			
		||||
			RS_PERIODIC_TIMEOUT_USEC *
 | 
			
		||||
			(u32)vdata->vnic_max_rate[vnic].vn_counter.rate / 8;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void bnx2x_init_min(const struct cmng_init_input *input_data,
 | 
			
		||||
				  u32 r_param, struct cmng_init *ram_data)
 | 
			
		||||
{
 | 
			
		||||
	u32 vnic, fair_periodic_timeout_usec, vnicWeightSum, tFair;
 | 
			
		||||
	struct cmng_vnic *vdata = &ram_data->vnic;
 | 
			
		||||
	struct cmng_struct_per_port *pdata = &ram_data->port;
 | 
			
		||||
 | 
			
		||||
	/* this is the resolution of the fairness timer */
 | 
			
		||||
	fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
 | 
			
		||||
 | 
			
		||||
	/* fairness per-port variables
 | 
			
		||||
	 * for 10G it is 1000usec. for 1G it is 10000usec.
 | 
			
		||||
	 */
 | 
			
		||||
	tFair = T_FAIR_COEF / input_data->port_rate;
 | 
			
		||||
 | 
			
		||||
	/* this is the threshold below which we won't arm the timer anymore */
 | 
			
		||||
	pdata->fair_vars.fair_threshold = QM_ARB_BYTES;
 | 
			
		||||
 | 
			
		||||
	/* we multiply by 1e3/8 to get bytes/msec. We don't want the credits
 | 
			
		||||
	 * to pass a credit of the T_FAIR*FAIR_MEM (algorithm resolution)
 | 
			
		||||
	 */
 | 
			
		||||
	pdata->fair_vars.upper_bound = r_param * tFair * FAIR_MEM;
 | 
			
		||||
 | 
			
		||||
	/* since each tick is 4 microSeconds */
 | 
			
		||||
	pdata->fair_vars.fairness_timeout =
 | 
			
		||||
				fair_periodic_timeout_usec / SDM_TICKS;
 | 
			
		||||
 | 
			
		||||
	/* calculate sum of weights */
 | 
			
		||||
	vnicWeightSum = 0;
 | 
			
		||||
 | 
			
		||||
	for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++)
 | 
			
		||||
		vnicWeightSum += input_data->vnic_min_rate[vnic];
 | 
			
		||||
 | 
			
		||||
	/* global vnic counter */
 | 
			
		||||
	if (vnicWeightSum > 0) {
 | 
			
		||||
		/* fairness per-vnic variables */
 | 
			
		||||
		for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++) {
 | 
			
		||||
			/* this is the credit for each period of the fairness
 | 
			
		||||
			 * algorithm - number of bytes in T_FAIR (this vnic
 | 
			
		||||
			 * share of the port rate)
 | 
			
		||||
			 */
 | 
			
		||||
			vdata->vnic_min_rate[vnic].vn_credit_delta =
 | 
			
		||||
				(u32)input_data->vnic_min_rate[vnic] * 100 *
 | 
			
		||||
				T_FAIR_COEF / (8 * 100 * vnicWeightSum);
 | 
			
		||||
			if (vdata->vnic_min_rate[vnic].vn_credit_delta <
 | 
			
		||||
			    pdata->fair_vars.fair_threshold +
 | 
			
		||||
			    MIN_ABOVE_THRESH) {
 | 
			
		||||
				vdata->vnic_min_rate[vnic].vn_credit_delta =
 | 
			
		||||
					pdata->fair_vars.fair_threshold +
 | 
			
		||||
					MIN_ABOVE_THRESH;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void bnx2x_init_fw_wrr(const struct cmng_init_input *input_data,
 | 
			
		||||
				     u32 r_param, struct cmng_init *ram_data)
 | 
			
		||||
{
 | 
			
		||||
	u32 vnic, cos;
 | 
			
		||||
	u32 cosWeightSum = 0;
 | 
			
		||||
	struct cmng_vnic *vdata = &ram_data->vnic;
 | 
			
		||||
	struct cmng_struct_per_port *pdata = &ram_data->port;
 | 
			
		||||
 | 
			
		||||
	for (cos = 0; cos < MAX_COS_NUMBER; cos++)
 | 
			
		||||
		cosWeightSum += input_data->cos_min_rate[cos];
 | 
			
		||||
 | 
			
		||||
	if (cosWeightSum > 0) {
 | 
			
		||||
 | 
			
		||||
		for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++) {
 | 
			
		||||
			/* Since cos and vnic shouldn't work together the rate
 | 
			
		||||
			 * to divide between the coses is the port rate.
 | 
			
		||||
			 */
 | 
			
		||||
			u32 *ccd = vdata->vnic_min_rate[vnic].cos_credit_delta;
 | 
			
		||||
			for (cos = 0; cos < MAX_COS_NUMBER; cos++) {
 | 
			
		||||
				/* this is the credit for each period of
 | 
			
		||||
				 * the fairness algorithm - number of bytes
 | 
			
		||||
				 * in T_FAIR (this cos share of the vnic rate)
 | 
			
		||||
				 */
 | 
			
		||||
				ccd[cos] =
 | 
			
		||||
				    (u32)input_data->cos_min_rate[cos] * 100 *
 | 
			
		||||
				    T_FAIR_COEF / (8 * 100 * cosWeightSum);
 | 
			
		||||
				 if (ccd[cos] < pdata->fair_vars.fair_threshold
 | 
			
		||||
						+ MIN_ABOVE_THRESH) {
 | 
			
		||||
					ccd[cos] =
 | 
			
		||||
					    pdata->fair_vars.fair_threshold +
 | 
			
		||||
					    MIN_ABOVE_THRESH;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void bnx2x_init_safc(const struct cmng_init_input *input_data,
 | 
			
		||||
				   struct cmng_init *ram_data)
 | 
			
		||||
{
 | 
			
		||||
	/* in microSeconds */
 | 
			
		||||
	ram_data->port.safc_vars.safc_timeout_usec = SAFC_TIMEOUT_USEC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Congestion management port init */
 | 
			
		||||
static inline void bnx2x_init_cmng(const struct cmng_init_input *input_data,
 | 
			
		||||
				   struct cmng_init *ram_data)
 | 
			
		||||
{
 | 
			
		||||
	u32 r_param;
 | 
			
		||||
	memset(ram_data, 0, sizeof(struct cmng_init));
 | 
			
		||||
 | 
			
		||||
	ram_data->port.flags = input_data->flags;
 | 
			
		||||
 | 
			
		||||
	/* number of bytes transmitted in a rate of 10Gbps
 | 
			
		||||
	 * in one usec = 1.25KB.
 | 
			
		||||
	 */
 | 
			
		||||
	r_param = BITS_TO_BYTES(input_data->port_rate);
 | 
			
		||||
	bnx2x_init_max(input_data, r_param, ram_data);
 | 
			
		||||
	bnx2x_init_min(input_data, r_param, ram_data);
 | 
			
		||||
	bnx2x_init_fw_wrr(input_data, r_param, ram_data);
 | 
			
		||||
	bnx2x_init_safc(input_data, ram_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Returns the index of start or end of a specific block stage in ops array */
 | 
			
		||||
#define BLOCK_OPS_IDX(block, stage, end) \
 | 
			
		||||
			(2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -499,9 +708,7 @@ static inline void bnx2x_disable_blocks_parity(struct bnx2x *bp)
 | 
			
		|||
	bnx2x_set_mcp_parity(bp, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Clear the parity error status registers.
 | 
			
		||||
 */
 | 
			
		||||
/* Clear the parity error status registers. */
 | 
			
		||||
static inline void bnx2x_clear_blocks_parity(struct bnx2x *bp)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2160,40 +2160,6 @@ u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes)
 | 
			
		|||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bnx2x_init_port_minmax(struct bnx2x *bp)
 | 
			
		||||
{
 | 
			
		||||
	u32 r_param = bp->link_vars.line_speed / 8;
 | 
			
		||||
	u32 fair_periodic_timeout_usec;
 | 
			
		||||
	u32 t_fair;
 | 
			
		||||
 | 
			
		||||
	memset(&(bp->cmng.rs_vars), 0,
 | 
			
		||||
	       sizeof(struct rate_shaping_vars_per_port));
 | 
			
		||||
	memset(&(bp->cmng.fair_vars), 0, sizeof(struct fairness_vars_per_port));
 | 
			
		||||
 | 
			
		||||
	/* 100 usec in SDM ticks = 25 since each tick is 4 usec */
 | 
			
		||||
	bp->cmng.rs_vars.rs_periodic_timeout = RS_PERIODIC_TIMEOUT_USEC / 4;
 | 
			
		||||
 | 
			
		||||
	/* this is the threshold below which no timer arming will occur
 | 
			
		||||
	   1.25 coefficient is for the threshold to be a little bigger
 | 
			
		||||
	   than the real time, to compensate for timer in-accuracy */
 | 
			
		||||
	bp->cmng.rs_vars.rs_threshold =
 | 
			
		||||
				(RS_PERIODIC_TIMEOUT_USEC * r_param * 5) / 4;
 | 
			
		||||
 | 
			
		||||
	/* resolution of fairness timer */
 | 
			
		||||
	fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
 | 
			
		||||
	/* for 10G it is 1000usec. for 1G it is 10000usec. */
 | 
			
		||||
	t_fair = T_FAIR_COEF / bp->link_vars.line_speed;
 | 
			
		||||
 | 
			
		||||
	/* this is the threshold below which we won't arm the timer anymore */
 | 
			
		||||
	bp->cmng.fair_vars.fair_threshold = QM_ARB_BYTES;
 | 
			
		||||
 | 
			
		||||
	/* we multiply by 1e3/8 to get bytes/msec.
 | 
			
		||||
	   We don't want the credits to pass a credit
 | 
			
		||||
	   of the t_fair*FAIR_MEM (algorithm resolution) */
 | 
			
		||||
	bp->cmng.fair_vars.upper_bound = r_param * t_fair * FAIR_MEM;
 | 
			
		||||
	/* since each tick is 4 usec */
 | 
			
		||||
	bp->cmng.fair_vars.fairness_timeout = fair_periodic_timeout_usec / 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Calculates the sum of vn_min_rates.
 | 
			
		||||
   It's needed for further normalizing of the min_rates.
 | 
			
		||||
| 
						 | 
				
			
			@ -2204,12 +2170,12 @@ static void bnx2x_init_port_minmax(struct bnx2x *bp)
 | 
			
		|||
     In the later case fainess algorithm should be deactivated.
 | 
			
		||||
     If not all min_rates are zero then those that are zeroes will be set to 1.
 | 
			
		||||
 */
 | 
			
		||||
static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
 | 
			
		||||
static void bnx2x_calc_vn_min(struct bnx2x *bp,
 | 
			
		||||
				      struct cmng_init_input *input)
 | 
			
		||||
{
 | 
			
		||||
	int all_zero = 1;
 | 
			
		||||
	int vn;
 | 
			
		||||
 | 
			
		||||
	bp->vn_weight_sum = 0;
 | 
			
		||||
	for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) {
 | 
			
		||||
		u32 vn_cfg = bp->mf_config[vn];
 | 
			
		||||
		u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
 | 
			
		||||
| 
						 | 
				
			
			@ -2217,106 +2183,56 @@ static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
 | 
			
		|||
 | 
			
		||||
		/* Skip hidden vns */
 | 
			
		||||
		if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
			vn_min_rate = 0;
 | 
			
		||||
		/* If min rate is zero - set it to 1 */
 | 
			
		||||
		if (!vn_min_rate)
 | 
			
		||||
		else if (!vn_min_rate)
 | 
			
		||||
			vn_min_rate = DEF_MIN_RATE;
 | 
			
		||||
		else
 | 
			
		||||
			all_zero = 0;
 | 
			
		||||
 | 
			
		||||
		bp->vn_weight_sum += vn_min_rate;
 | 
			
		||||
		input->vnic_min_rate[vn] = vn_min_rate;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* if ETS or all min rates are zeros - disable fairness */
 | 
			
		||||
	if (BNX2X_IS_ETS_ENABLED(bp)) {
 | 
			
		||||
		bp->cmng.flags.cmng_enables &=
 | 
			
		||||
		input->flags.cmng_enables &=
 | 
			
		||||
					~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
 | 
			
		||||
		DP(NETIF_MSG_IFUP, "Fairness will be disabled due to ETS\n");
 | 
			
		||||
	} else if (all_zero) {
 | 
			
		||||
		bp->cmng.flags.cmng_enables &=
 | 
			
		||||
		input->flags.cmng_enables &=
 | 
			
		||||
					~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
 | 
			
		||||
		DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
 | 
			
		||||
		   "  fairness will be disabled\n");
 | 
			
		||||
		DP(NETIF_MSG_IFUP,
 | 
			
		||||
		   "All MIN values are zeroes fairness will be disabled\n");
 | 
			
		||||
	} else
 | 
			
		||||
		bp->cmng.flags.cmng_enables |=
 | 
			
		||||
		input->flags.cmng_enables |=
 | 
			
		||||
					CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bnx2x_init_vn_minmax(struct bnx2x *bp, int vn)
 | 
			
		||||
static void bnx2x_calc_vn_max(struct bnx2x *bp, int vn,
 | 
			
		||||
				    struct cmng_init_input *input)
 | 
			
		||||
{
 | 
			
		||||
	struct rate_shaping_vars_per_vn m_rs_vn;
 | 
			
		||||
	struct fairness_vars_per_vn m_fair_vn;
 | 
			
		||||
	u16 vn_max_rate;
 | 
			
		||||
	u32 vn_cfg = bp->mf_config[vn];
 | 
			
		||||
	int func = func_by_vn(bp, vn);
 | 
			
		||||
	u16 vn_min_rate, vn_max_rate;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	/* If function is hidden - set min and max to zeroes */
 | 
			
		||||
	if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE) {
 | 
			
		||||
		vn_min_rate = 0;
 | 
			
		||||
	if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE)
 | 
			
		||||
		vn_max_rate = 0;
 | 
			
		||||
 | 
			
		||||
	} else {
 | 
			
		||||
	else {
 | 
			
		||||
		u32 maxCfg = bnx2x_extract_max_cfg(bp, vn_cfg);
 | 
			
		||||
 | 
			
		||||
		vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
 | 
			
		||||
				FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
 | 
			
		||||
		/* If fairness is enabled (not all min rates are zeroes) and
 | 
			
		||||
		   if current min rate is zero - set it to 1.
 | 
			
		||||
		   This is a requirement of the algorithm. */
 | 
			
		||||
		if (bp->vn_weight_sum && (vn_min_rate == 0))
 | 
			
		||||
			vn_min_rate = DEF_MIN_RATE;
 | 
			
		||||
 | 
			
		||||
		if (IS_MF_SI(bp))
 | 
			
		||||
		if (IS_MF_SI(bp)) {
 | 
			
		||||
			/* maxCfg in percents of linkspeed */
 | 
			
		||||
			vn_max_rate = (bp->link_vars.line_speed * maxCfg) / 100;
 | 
			
		||||
		else
 | 
			
		||||
		} else /* SD modes */
 | 
			
		||||
			/* maxCfg is absolute in 100Mb units */
 | 
			
		||||
			vn_max_rate = maxCfg * 100;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DP(NETIF_MSG_IFUP,
 | 
			
		||||
	   "func %d: vn_min_rate %d  vn_max_rate %d  vn_weight_sum %d\n",
 | 
			
		||||
	   func, vn_min_rate, vn_max_rate, bp->vn_weight_sum);
 | 
			
		||||
	DP(NETIF_MSG_IFUP, "vn %d: vn_max_rate %d\n", vn, vn_max_rate);
 | 
			
		||||
 | 
			
		||||
	memset(&m_rs_vn, 0, sizeof(struct rate_shaping_vars_per_vn));
 | 
			
		||||
	memset(&m_fair_vn, 0, sizeof(struct fairness_vars_per_vn));
 | 
			
		||||
 | 
			
		||||
	/* global vn counter - maximal Mbps for this vn */
 | 
			
		||||
	m_rs_vn.vn_counter.rate = vn_max_rate;
 | 
			
		||||
 | 
			
		||||
	/* quota - number of bytes transmitted in this period */
 | 
			
		||||
	m_rs_vn.vn_counter.quota =
 | 
			
		||||
				(vn_max_rate * RS_PERIODIC_TIMEOUT_USEC) / 8;
 | 
			
		||||
 | 
			
		||||
	if (bp->vn_weight_sum) {
 | 
			
		||||
		/* credit for each period of the fairness algorithm:
 | 
			
		||||
		   number of bytes in T_FAIR (the vn share the port rate).
 | 
			
		||||
		   vn_weight_sum should not be larger than 10000, thus
 | 
			
		||||
		   T_FAIR_COEF / (8 * vn_weight_sum) will always be greater
 | 
			
		||||
		   than zero */
 | 
			
		||||
		m_fair_vn.vn_credit_delta =
 | 
			
		||||
			max_t(u32, (vn_min_rate * (T_FAIR_COEF /
 | 
			
		||||
						   (8 * bp->vn_weight_sum))),
 | 
			
		||||
			      (bp->cmng.fair_vars.fair_threshold +
 | 
			
		||||
							MIN_ABOVE_THRESH));
 | 
			
		||||
		DP(NETIF_MSG_IFUP, "m_fair_vn.vn_credit_delta %d\n",
 | 
			
		||||
		   m_fair_vn.vn_credit_delta);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Store it to internal memory */
 | 
			
		||||
	for (i = 0; i < sizeof(struct rate_shaping_vars_per_vn)/4; i++)
 | 
			
		||||
		REG_WR(bp, BAR_XSTRORM_INTMEM +
 | 
			
		||||
		       XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(func) + i * 4,
 | 
			
		||||
		       ((u32 *)(&m_rs_vn))[i]);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sizeof(struct fairness_vars_per_vn)/4; i++)
 | 
			
		||||
		REG_WR(bp, BAR_XSTRORM_INTMEM +
 | 
			
		||||
		       XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(func) + i * 4,
 | 
			
		||||
		       ((u32 *)(&m_fair_vn))[i]);
 | 
			
		||||
	input->vnic_max_rate[vn] = vn_max_rate;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp)
 | 
			
		||||
{
 | 
			
		||||
	if (CHIP_REV_IS_SLOW(bp))
 | 
			
		||||
| 
						 | 
				
			
			@ -2358,34 +2274,31 @@ void bnx2x_read_mf_cfg(struct bnx2x *bp)
 | 
			
		|||
 | 
			
		||||
static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type)
 | 
			
		||||
{
 | 
			
		||||
	struct cmng_init_input input;
 | 
			
		||||
	memset(&input, 0, sizeof(struct cmng_init_input));
 | 
			
		||||
 | 
			
		||||
	input.port_rate = bp->link_vars.line_speed;
 | 
			
		||||
 | 
			
		||||
	if (cmng_type == CMNG_FNS_MINMAX) {
 | 
			
		||||
		int vn;
 | 
			
		||||
 | 
			
		||||
		/* clear cmng_enables */
 | 
			
		||||
		bp->cmng.flags.cmng_enables = 0;
 | 
			
		||||
 | 
			
		||||
		/* read mf conf from shmem */
 | 
			
		||||
		if (read_cfg)
 | 
			
		||||
			bnx2x_read_mf_cfg(bp);
 | 
			
		||||
 | 
			
		||||
		/* Init rate shaping and fairness contexts */
 | 
			
		||||
		bnx2x_init_port_minmax(bp);
 | 
			
		||||
 | 
			
		||||
		/* vn_weight_sum and enable fairness if not 0 */
 | 
			
		||||
		bnx2x_calc_vn_weight_sum(bp);
 | 
			
		||||
		bnx2x_calc_vn_min(bp, &input);
 | 
			
		||||
 | 
			
		||||
		/* calculate and set min-max rate for each vn */
 | 
			
		||||
		if (bp->port.pmf)
 | 
			
		||||
			for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++)
 | 
			
		||||
				bnx2x_init_vn_minmax(bp, vn);
 | 
			
		||||
				bnx2x_calc_vn_max(bp, vn, &input);
 | 
			
		||||
 | 
			
		||||
		/* always enable rate shaping and fairness */
 | 
			
		||||
		bp->cmng.flags.cmng_enables |=
 | 
			
		||||
		input.flags.cmng_enables |=
 | 
			
		||||
					CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN;
 | 
			
		||||
		if (!bp->vn_weight_sum)
 | 
			
		||||
			DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
 | 
			
		||||
				   "  fairness will be disabled\n");
 | 
			
		||||
 | 
			
		||||
		bnx2x_init_cmng(&input, &bp->cmng);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue