#include "lm5710.h"
#include "init_defs.h"
#define ECORE_PORT2_MODE_NUM_VNICS 4
#define ECORE_ETH_Q 0
#define ECORE_TOE_Q 3
#define ECORE_TOE_ACK_Q 6
#define ECORE_ISCSI_Q 9
#define ECORE_ISCSI_ACK_Q 11
#define ECORE_FCOE_Q 10
#define ECORE_PORT4_MODE_NUM_VNICS 2
#define ECORE_E3B0_PORT1_COS_OFFSET 3
#define ECORE_Q_VOQ_REG_ADDR(pf_q_num)\
(QM_REG_QVOQIDX_0 + 4 * (pf_q_num))
#define ECORE_VOQ_Q_REG_ADDR(cos, pf_q_num)\
(QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5)))
#define ECORE_Q_CMDQ_REG_ADDR(pf_q_num)\
(QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4))
#define ECORE_PF_Q_NUM(q_num, port, vnic)\
((((port) << 1) | (vnic)) * 16 + (q_num))
void ecore_map_q_cos(struct _lm_device_t *pdev, u32_t q_num, u32_t new_cos)
{
u32_t curr_cos = REG_RD(pdev, QM_REG_QVOQIDX_0 + q_num * 4);
if (curr_cos != new_cos) {
u32_t num_vnics = ECORE_PORT2_MODE_NUM_VNICS;
u32_t reg_addr, reg_bit_map, vnic;
if (INIT_MODE_FLAGS(pdev) & MODE_PORT4) {
num_vnics = ECORE_PORT4_MODE_NUM_VNICS;
if (PORT_ID(pdev)) {
curr_cos += ECORE_E3B0_PORT1_COS_OFFSET;
new_cos += ECORE_E3B0_PORT1_COS_OFFSET;
}
}
for (vnic = 0; vnic < num_vnics; vnic++) {
u32_t pf_q_num =
ECORE_PF_Q_NUM(q_num, PORT_ID(pdev), vnic);
u32_t q_bit_map = 1 << (pf_q_num & 0x1f);
REG_WR(pdev, ECORE_Q_VOQ_REG_ADDR(pf_q_num), new_cos);
reg_addr = ECORE_VOQ_Q_REG_ADDR(curr_cos, pf_q_num);
reg_bit_map = REG_RD(pdev, reg_addr);
REG_WR(pdev, reg_addr, reg_bit_map & (~q_bit_map));
reg_addr = ECORE_VOQ_Q_REG_ADDR(new_cos, pf_q_num);
reg_bit_map = REG_RD(pdev, reg_addr);
REG_WR(pdev, reg_addr, reg_bit_map | q_bit_map);
if (!(INIT_MODE_FLAGS(pdev) & MODE_E3_B0)) {
reg_addr = ECORE_Q_CMDQ_REG_ADDR(pf_q_num);
reg_bit_map = REG_RD(pdev, reg_addr);
q_bit_map = 1 << (2 * (pf_q_num & 0xf));
reg_bit_map = new_cos ?
(reg_bit_map | q_bit_map) :
(reg_bit_map & (~q_bit_map));
REG_WR(pdev, reg_addr, reg_bit_map);
}
}
}
}
void ecore_dcb_config_qm(struct _lm_device_t *pdev, enum cos_mode mode,
struct priority_cos *traffic_cos)
{
ecore_map_q_cos(pdev, ECORE_FCOE_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos);
ecore_map_q_cos(pdev, ECORE_ISCSI_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
ecore_map_q_cos(pdev, ECORE_ISCSI_ACK_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
if (mode != STATIC_COS) {
ecore_map_q_cos(pdev, ECORE_ETH_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
ecore_map_q_cos(pdev, ECORE_TOE_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
ecore_map_q_cos(pdev, ECORE_TOE_ACK_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
}
}
#define BITS_TO_BYTES(x) ((x)/8)
#define DEF_MIN_RATE 100
#define RS_PERIODIC_TIMEOUT_USEC 400
#define QM_ARB_BYTES 160000
#define MIN_RES 100
#define MIN_ABOVE_THRESH 32768
#define T_FAIR_COEF ((MIN_ABOVE_THRESH + QM_ARB_BYTES) * 8 * MIN_RES)
#define FAIR_MEM 2
#define SAFC_TIMEOUT_USEC 52
#define SDM_TICKS 4
void ecore_init_max(const struct cmng_init_input *input_data,
u32_t r_param, struct cmng_init *ram_data)
{
u32_t vnic;
struct cmng_vnic *vdata = &ram_data->vnic;
struct cmng_struct_per_port *pdata = &ram_data->port;
pdata->rs_vars.rs_periodic_timeout =
RS_PERIODIC_TIMEOUT_USEC / SDM_TICKS;
pdata->rs_vars.rs_threshold =
(5 * RS_PERIODIC_TIMEOUT_USEC * r_param)/4;
for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) {
vdata->vnic_max_rate[vnic].vn_counter.rate =
input_data->vnic_max_rate[vnic];
vdata->vnic_max_rate[vnic].vn_counter.quota =
RS_PERIODIC_TIMEOUT_USEC *
(u32_t)vdata->vnic_max_rate[vnic].vn_counter.rate / 8;
}
}
void ecore_init_max_per_vn(u16_t vnic_max_rate,
struct rate_shaping_vars_per_vn *ram_data)
{
ram_data->vn_counter.rate = vnic_max_rate;
ram_data->vn_counter.quota =
RS_PERIODIC_TIMEOUT_USEC * (u32_t)vnic_max_rate / 8;
}
void ecore_init_min(const struct cmng_init_input *input_data,
u32_t r_param, struct cmng_init *ram_data)
{
u32_t vnic, fair_periodic_timeout_usec, vnicWeightSum, tFair;
struct cmng_vnic *vdata = &ram_data->vnic;
struct cmng_struct_per_port *pdata = &ram_data->port;
fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
tFair = T_FAIR_COEF / input_data->port_rate;
pdata->fair_vars.fair_threshold = QM_ARB_BYTES;
pdata->fair_vars.upper_bound = r_param * tFair * FAIR_MEM;
pdata->fair_vars.fairness_timeout =
fair_periodic_timeout_usec / SDM_TICKS;
vnicWeightSum = 0;
for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++)
vnicWeightSum += input_data->vnic_min_rate[vnic];
if (vnicWeightSum > 0) {
for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) {
vdata->vnic_min_rate[vnic].vn_credit_delta =
((u32_t)(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;
}
}
}
}
void ecore_init_fw_wrr(const struct cmng_init_input *input_data,
u32_t r_param, struct cmng_init *ram_data)
{
u32_t vnic, cos;
u32_t 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 < ECORE_PORT2_MODE_NUM_VNICS; vnic++) {
u32_t *ccd = vdata->vnic_min_rate[vnic].cos_credit_delta;
for (cos = 0; cos < MAX_COS_NUMBER; cos++) {
ccd[cos] =
((u32_t)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;
}
}
}
}
}
void ecore_init_safc(const struct cmng_init_input *input_data,
struct cmng_init *ram_data)
{
ram_data->port.safc_vars.safc_timeout_usec = SAFC_TIMEOUT_USEC;
}
void ecore_init_cmng(const struct cmng_init_input *input_data,
struct cmng_init *ram_data)
{
u32_t r_param;
mm_mem_zero(ram_data,sizeof(struct cmng_init));
ram_data->port.flags = input_data->flags;
r_param = BITS_TO_BYTES(input_data->port_rate);
ecore_init_max(input_data, r_param, ram_data);
ecore_init_min(input_data, r_param, ram_data);
ecore_init_fw_wrr(input_data, r_param, ram_data);
ecore_init_safc(input_data, ram_data);
}