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:
Yuval Mintz 2012-04-03 18:41:29 +00:00 committed by David S. Miller
parent 7e8e02df17
commit b475d78f46
5 changed files with 331 additions and 163 deletions

View File

@ -30,6 +30,10 @@
#if defined(CONFIG_DCB) #if defined(CONFIG_DCB)
#define BCM_DCBNL #define BCM_DCBNL
#endif #endif
#include "bnx2x_hsi.h"
#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
#define BCM_CNIC 1 #define BCM_CNIC 1
#include "../cnic_if.h" #include "../cnic_if.h"
@ -1336,8 +1340,8 @@ struct bnx2x {
struct bnx2x_common common; struct bnx2x_common common;
struct bnx2x_port port; struct bnx2x_port port;
struct cmng_struct_per_port cmng; struct cmng_init cmng;
u32 vn_weight_sum;
u32 mf_config[E1HVN_MAX]; u32 mf_config[E1HVN_MAX];
u32 mf2_config[E2_FUNC_MAX]; u32 mf2_config[E2_FUNC_MAX];
u32 path_has_ovlan; /* E3 */ u32 path_has_ovlan; /* E3 */

View File

@ -964,6 +964,12 @@ static inline void bnx2x_reuse_rx_data(struct bnx2x_fastpath *fp,
/************************* Init ******************************************/ /************************* 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 * 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, static inline void storm_memset_cmng(struct bnx2x *bp,
struct cmng_struct_per_port *cmng, struct cmng_init *cmng,
u8 port) u8 port)
{ {
int vn;
size_t size = sizeof(struct cmng_struct_per_port); size_t size = sizeof(struct cmng_struct_per_port);
u32 addr = BAR_XSTRORM_INTMEM + u32 addr = BAR_XSTRORM_INTMEM +
XSTORM_CMNG_PER_PORT_VARS_OFFSET(port); 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); void bnx2x_get_iscsi_info(struct bnx2x *bp);
#endif #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. * bnx2x_link_sync_notify - send notification to other functions.

View File

@ -4448,6 +4448,65 @@ struct cmng_struct_per_port {
struct cmng_flags_per_port flags; 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 * 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 * 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 * The send queue element
*/ */

View File

@ -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); REG_WR(bp, reg_addr, reg_bit_map | q_bit_map);
/* set/clear queue bit in command-queue 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)) { if (!(INIT_MODE_FLAGS(bp) & MODE_E3_B0)) {
reg_addr = BNX2X_Q_CMDQ_REG_ADDR(pf_q_num); reg_addr = BNX2X_Q_CMDQ_REG_ADDR(pf_q_num);
reg_bit_map = REG_RD(bp, reg_addr); reg_bit_map = REG_RD(bp, reg_addr);
@ -277,6 +278,214 @@ static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode,
} }
/* 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 */ /* Returns the index of start or end of a specific block stage in ops array */
#define BLOCK_OPS_IDX(block, stage, end) \ #define BLOCK_OPS_IDX(block, stage, end) \
(2*(((block)*NUM_OF_INIT_PHASES) + (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); 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) static inline void bnx2x_clear_blocks_parity(struct bnx2x *bp)
{ {
int i; int i;

View File

@ -2160,40 +2160,6 @@ u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes)
return rc; 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. /* Calculates the sum of vn_min_rates.
It's needed for further normalizing of the 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. 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. 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 all_zero = 1;
int vn; int vn;
bp->vn_weight_sum = 0;
for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) { for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) {
u32 vn_cfg = bp->mf_config[vn]; u32 vn_cfg = bp->mf_config[vn];
u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >> u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
@ -2217,105 +2183,55 @@ static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
/* Skip hidden vns */ /* Skip hidden vns */
if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE) if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE)
continue; vn_min_rate = 0;
/* If min rate is zero - set it to 1 */ /* If min rate is zero - set it to 1 */
if (!vn_min_rate) else if (!vn_min_rate)
vn_min_rate = DEF_MIN_RATE; vn_min_rate = DEF_MIN_RATE;
else else
all_zero = 0; 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 ETS or all min rates are zeros - disable fairness */
if (BNX2X_IS_ETS_ENABLED(bp)) { if (BNX2X_IS_ETS_ENABLED(bp)) {
bp->cmng.flags.cmng_enables &= input->flags.cmng_enables &=
~CMNG_FLAGS_PER_PORT_FAIRNESS_VN; ~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
DP(NETIF_MSG_IFUP, "Fairness will be disabled due to ETS\n"); DP(NETIF_MSG_IFUP, "Fairness will be disabled due to ETS\n");
} else if (all_zero) { } else if (all_zero) {
bp->cmng.flags.cmng_enables &= input->flags.cmng_enables &=
~CMNG_FLAGS_PER_PORT_FAIRNESS_VN; ~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
DP(NETIF_MSG_IFUP, "All MIN values are zeroes" DP(NETIF_MSG_IFUP,
" fairness will be disabled\n"); "All MIN values are zeroes fairness will be disabled\n");
} else } else
bp->cmng.flags.cmng_enables |= input->flags.cmng_enables |=
CMNG_FLAGS_PER_PORT_FAIRNESS_VN; 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; u16 vn_max_rate;
struct fairness_vars_per_vn m_fair_vn;
u32 vn_cfg = bp->mf_config[vn]; 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)
if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE) {
vn_min_rate = 0;
vn_max_rate = 0; vn_max_rate = 0;
else {
} else {
u32 maxCfg = bnx2x_extract_max_cfg(bp, vn_cfg); u32 maxCfg = bnx2x_extract_max_cfg(bp, vn_cfg);
vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >> if (IS_MF_SI(bp)) {
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))
/* maxCfg in percents of linkspeed */ /* maxCfg in percents of linkspeed */
vn_max_rate = (bp->link_vars.line_speed * maxCfg) / 100; vn_max_rate = (bp->link_vars.line_speed * maxCfg) / 100;
else } else /* SD modes */
/* maxCfg is absolute in 100Mb units */ /* maxCfg is absolute in 100Mb units */
vn_max_rate = maxCfg * 100; vn_max_rate = maxCfg * 100;
} }
DP(NETIF_MSG_IFUP, DP(NETIF_MSG_IFUP, "vn %d: vn_max_rate %d\n", vn, vn_max_rate);
"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);
memset(&m_rs_vn, 0, sizeof(struct rate_shaping_vars_per_vn)); input->vnic_max_rate[vn] = vn_max_rate;
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]);
}
static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp) static int bnx2x_get_cmng_fns_mode(struct bnx2x *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) 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) { if (cmng_type == CMNG_FNS_MINMAX) {
int vn; int vn;
/* clear cmng_enables */
bp->cmng.flags.cmng_enables = 0;
/* read mf conf from shmem */ /* read mf conf from shmem */
if (read_cfg) if (read_cfg)
bnx2x_read_mf_cfg(bp); 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 */ /* 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 */ /* calculate and set min-max rate for each vn */
if (bp->port.pmf) if (bp->port.pmf)
for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) 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 */ /* always enable rate shaping and fairness */
bp->cmng.flags.cmng_enables |= input.flags.cmng_enables |=
CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN; CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN;
if (!bp->vn_weight_sum)
DP(NETIF_MSG_IFUP, "All MIN values are zeroes" bnx2x_init_cmng(&input, &bp->cmng);
" fairness will be disabled\n");
return; return;
} }