1 2 3 4 5 #include "lm5710.h" 6 #include "init_defs.h" 7 8 /* Vnics per mode */ 9 #define ECORE_PORT2_MODE_NUM_VNICS 4 10 11 12 /* QM queue numbers */ 13 #define ECORE_ETH_Q 0 14 #define ECORE_TOE_Q 3 15 #define ECORE_TOE_ACK_Q 6 16 #define ECORE_ISCSI_Q 9 17 #define ECORE_ISCSI_ACK_Q 11 18 #define ECORE_FCOE_Q 10 19 20 /* Vnics per mode */ 21 #define ECORE_PORT4_MODE_NUM_VNICS 2 22 23 /* COS offset for port1 in E3 B0 4port mode */ 24 #define ECORE_E3B0_PORT1_COS_OFFSET 3 25 26 /* QM Register addresses */ 27 #define ECORE_Q_VOQ_REG_ADDR(pf_q_num)\ 28 (QM_REG_QVOQIDX_0 + 4 * (pf_q_num)) 29 #define ECORE_VOQ_Q_REG_ADDR(cos, pf_q_num)\ 30 (QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5))) 31 #define ECORE_Q_CMDQ_REG_ADDR(pf_q_num)\ 32 (QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4)) 33 34 /* extracts the QM queue number for the specified port and vnic */ 35 #define ECORE_PF_Q_NUM(q_num, port, vnic)\ 36 ((((port) << 1) | (vnic)) * 16 + (q_num)) 37 38 39 /* Maps the specified queue to the specified COS */ 40 void ecore_map_q_cos(struct _lm_device_t *pdev, u32_t q_num, u32_t new_cos) 41 { 42 /* find current COS mapping */ 43 u32_t curr_cos = REG_RD(pdev, QM_REG_QVOQIDX_0 + q_num * 4); 44 45 /* check if queue->COS mapping has changed */ 46 if (curr_cos != new_cos) { 47 u32_t num_vnics = ECORE_PORT2_MODE_NUM_VNICS; 48 u32_t reg_addr, reg_bit_map, vnic; 49 50 /* update parameters for 4port mode */ 51 if (INIT_MODE_FLAGS(pdev) & MODE_PORT4) { 52 num_vnics = ECORE_PORT4_MODE_NUM_VNICS; 53 if (PORT_ID(pdev)) { 54 curr_cos += ECORE_E3B0_PORT1_COS_OFFSET; 55 new_cos += ECORE_E3B0_PORT1_COS_OFFSET; 56 } 57 } 58 59 /* change queue mapping for each VNIC */ 60 for (vnic = 0; vnic < num_vnics; vnic++) { 61 u32_t pf_q_num = 62 ECORE_PF_Q_NUM(q_num, PORT_ID(pdev), vnic); 63 u32_t q_bit_map = 1 << (pf_q_num & 0x1f); 64 65 /* overwrite queue->VOQ mapping */ 66 REG_WR(pdev, ECORE_Q_VOQ_REG_ADDR(pf_q_num), new_cos); 67 68 /* clear queue bit from current COS bit map */ 69 reg_addr = ECORE_VOQ_Q_REG_ADDR(curr_cos, pf_q_num); 70 reg_bit_map = REG_RD(pdev, reg_addr); 71 REG_WR(pdev, reg_addr, reg_bit_map & (~q_bit_map)); 72 73 /* set queue bit in new COS bit map */ 74 reg_addr = ECORE_VOQ_Q_REG_ADDR(new_cos, pf_q_num); 75 reg_bit_map = REG_RD(pdev, reg_addr); 76 REG_WR(pdev, reg_addr, reg_bit_map | q_bit_map); 77 78 /* set/clear queue bit in command-queue bit map 79 (E2/E3A0 only, valid COS values are 0/1) */ 80 if (!(INIT_MODE_FLAGS(pdev) & MODE_E3_B0)) { 81 reg_addr = ECORE_Q_CMDQ_REG_ADDR(pf_q_num); 82 reg_bit_map = REG_RD(pdev, reg_addr); 83 q_bit_map = 1 << (2 * (pf_q_num & 0xf)); 84 reg_bit_map = new_cos ? 85 (reg_bit_map | q_bit_map) : 86 (reg_bit_map & (~q_bit_map)); 87 REG_WR(pdev, reg_addr, reg_bit_map); 88 } 89 } 90 } 91 } 92 93 /* Configures the QM according to the specified per-traffic-type COSes */ 94 void ecore_dcb_config_qm(struct _lm_device_t *pdev, enum cos_mode mode, 95 struct priority_cos *traffic_cos) 96 { 97 ecore_map_q_cos(pdev, ECORE_FCOE_Q, 98 traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos); 99 ecore_map_q_cos(pdev, ECORE_ISCSI_Q, 100 traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); 101 ecore_map_q_cos(pdev, ECORE_ISCSI_ACK_Q, 102 traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); 103 if (mode != STATIC_COS) { 104 /* required only in OVERRIDE_COS mode */ 105 ecore_map_q_cos(pdev, ECORE_ETH_Q, 106 traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); 107 ecore_map_q_cos(pdev, ECORE_TOE_Q, 108 traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); 109 ecore_map_q_cos(pdev, ECORE_TOE_ACK_Q, 110 traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); 111 } 112 } 113 114 115 /* 116 * congestion managment port init api description 117 * the api works as follows: 118 * the driver should pass the cmng_init_input struct, the port_init function 119 * will prepare the required internal ram structure which will be passed back 120 * to the driver (cmng_init) that will write it into the internal ram. 121 * 122 * IMPORTANT REMARKS: 123 * 1. the cmng_init struct does not represent the contiguous internal ram 124 * structure. the driver should use the XSTORM_CMNG_PERPORT_VARS_OFFSET 125 * offset in order to write the port sub struct and the 126 * PFID_FROM_PORT_AND_VNIC offset for writing the vnic sub struct (in other 127 * words - don't use memcpy!). 128 * 2. although the cmng_init struct is filled for the maximal vnic number 129 * possible, the driver should only write the valid vnics into the internal 130 * ram according to the appropriate port mode. 131 */ 132 #define BITS_TO_BYTES(x) ((x)/8) 133 134 /* CMNG constants, as derived from system spec calculations */ 135 136 /* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */ 137 #define DEF_MIN_RATE 100 138 139 /* resolution of the rate shaping timer - 400 usec */ 140 #define RS_PERIODIC_TIMEOUT_USEC 400 141 142 /* 143 * number of bytes in single QM arbitration cycle - 144 * coefficient for calculating the fairness timer 145 */ 146 #define QM_ARB_BYTES 160000 147 148 /* resolution of Min algorithm 1:100 */ 149 #define MIN_RES 100 150 151 /* 152 * how many bytes above threshold for 153 * the minimal credit of Min algorithm 154 */ 155 #define MIN_ABOVE_THRESH 32768 156 157 /* 158 * Fairness algorithm integration time coefficient - 159 * for calculating the actual Tfair 160 */ 161 #define T_FAIR_COEF ((MIN_ABOVE_THRESH + QM_ARB_BYTES) * 8 * MIN_RES) 162 163 /* Memory of fairness algorithm - 2 cycles */ 164 #define FAIR_MEM 2 165 #define SAFC_TIMEOUT_USEC 52 166 167 #define SDM_TICKS 4 168 169 170 void ecore_init_max(const struct cmng_init_input *input_data, 171 u32_t r_param, struct cmng_init *ram_data) 172 { 173 u32_t vnic; 174 struct cmng_vnic *vdata = &ram_data->vnic; 175 struct cmng_struct_per_port *pdata = &ram_data->port; 176 /* 177 * rate shaping per-port variables 178 * 100 micro seconds in SDM ticks = 25 179 * since each tick is 4 microSeconds 180 */ 181 182 pdata->rs_vars.rs_periodic_timeout = 183 RS_PERIODIC_TIMEOUT_USEC / SDM_TICKS; 184 185 /* this is the threshold below which no timer arming will occur. 186 * 1.25 coefficient is for the threshold to be a little bigger 187 * then the real time to compensate for timer in-accuracy 188 */ 189 pdata->rs_vars.rs_threshold = 190 (5 * RS_PERIODIC_TIMEOUT_USEC * r_param)/4; 191 192 /* rate shaping per-vnic variables */ 193 for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) { 194 /* global vnic counter */ 195 vdata->vnic_max_rate[vnic].vn_counter.rate = 196 input_data->vnic_max_rate[vnic]; 197 /* 198 * maximal Mbps for this vnic 199 * the quota in each timer period - number of bytes 200 * transmitted in this period 201 */ 202 vdata->vnic_max_rate[vnic].vn_counter.quota = 203 RS_PERIODIC_TIMEOUT_USEC * 204 (u32_t)vdata->vnic_max_rate[vnic].vn_counter.rate / 8; 205 } 206 207 } 208 209 void ecore_init_max_per_vn(u16_t vnic_max_rate, 210 struct rate_shaping_vars_per_vn *ram_data) 211 { 212 /* global vnic counter */ 213 ram_data->vn_counter.rate = vnic_max_rate; 214 215 /* 216 * maximal Mbps for this vnic 217 * the quota in each timer period - number of bytes 218 * transmitted in this period 219 */ 220 ram_data->vn_counter.quota = 221 RS_PERIODIC_TIMEOUT_USEC * (u32_t)vnic_max_rate / 8; 222 } 223 224 void ecore_init_min(const struct cmng_init_input *input_data, 225 u32_t r_param, struct cmng_init *ram_data) 226 { 227 u32_t vnic, fair_periodic_timeout_usec, vnicWeightSum, tFair; 228 struct cmng_vnic *vdata = &ram_data->vnic; 229 struct cmng_struct_per_port *pdata = &ram_data->port; 230 231 /* this is the resolution of the fairness timer */ 232 fair_periodic_timeout_usec = QM_ARB_BYTES / r_param; 233 234 /* 235 * fairness per-port variables 236 * for 10G it is 1000usec. for 1G it is 10000usec. 237 */ 238 tFair = T_FAIR_COEF / input_data->port_rate; 239 240 /* this is the threshold below which we won't arm the timer anymore */ 241 pdata->fair_vars.fair_threshold = QM_ARB_BYTES; 242 243 /* 244 * we multiply by 1e3/8 to get bytes/msec. We don't want the credits 245 * to pass a credit of the T_FAIR*FAIR_MEM (algorithm resolution) 246 */ 247 pdata->fair_vars.upper_bound = r_param * tFair * FAIR_MEM; 248 249 /* since each tick is 4 microSeconds */ 250 pdata->fair_vars.fairness_timeout = 251 fair_periodic_timeout_usec / SDM_TICKS; 252 253 /* calculate sum of weights */ 254 vnicWeightSum = 0; 255 256 for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) 257 vnicWeightSum += input_data->vnic_min_rate[vnic]; 258 259 /* global vnic counter */ 260 if (vnicWeightSum > 0) { 261 /* fairness per-vnic variables */ 262 for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) { 263 /* 264 * this is the credit for each period of the fairness 265 * algorithm - number of bytes in T_FAIR (this vnic 266 * share of the port rate) 267 */ 268 vdata->vnic_min_rate[vnic].vn_credit_delta = 269 ((u32_t)(input_data->vnic_min_rate[vnic]) * 100 * 270 (T_FAIR_COEF / (8 * 100 * vnicWeightSum))); 271 if (vdata->vnic_min_rate[vnic].vn_credit_delta < 272 pdata->fair_vars.fair_threshold + 273 MIN_ABOVE_THRESH) { 274 vdata->vnic_min_rate[vnic].vn_credit_delta = 275 pdata->fair_vars.fair_threshold + 276 MIN_ABOVE_THRESH; 277 } 278 } 279 } 280 } 281 282 void ecore_init_fw_wrr(const struct cmng_init_input *input_data, 283 u32_t r_param, struct cmng_init *ram_data) 284 { 285 u32_t vnic, cos; 286 u32_t cosWeightSum = 0; 287 struct cmng_vnic *vdata = &ram_data->vnic; 288 struct cmng_struct_per_port *pdata = &ram_data->port; 289 290 for (cos = 0; cos < MAX_COS_NUMBER; cos++) 291 cosWeightSum += input_data->cos_min_rate[cos]; 292 293 if (cosWeightSum > 0) { 294 295 for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) { 296 /* 297 * Since cos and vnic shouldn't work together the rate 298 * to divide between the coses is the port rate. 299 */ 300 u32_t *ccd = vdata->vnic_min_rate[vnic].cos_credit_delta; 301 for (cos = 0; cos < MAX_COS_NUMBER; cos++) { 302 /* 303 * this is the credit for each period of 304 * the fairness algorithm - number of bytes 305 * in T_FAIR (this cos share of the vnic rate) 306 */ 307 ccd[cos] = 308 ((u32_t)input_data->cos_min_rate[cos] * 100 * 309 (T_FAIR_COEF / (8 * 100 * cosWeightSum))); 310 if (ccd[cos] < pdata->fair_vars.fair_threshold 311 + MIN_ABOVE_THRESH) { 312 ccd[cos] = 313 pdata->fair_vars.fair_threshold + 314 MIN_ABOVE_THRESH; 315 } 316 } 317 } 318 } 319 } 320 321 void ecore_init_safc(const struct cmng_init_input *input_data, 322 struct cmng_init *ram_data) 323 { 324 /* in microSeconds */ 325 ram_data->port.safc_vars.safc_timeout_usec = SAFC_TIMEOUT_USEC; 326 } 327 328 /* Congestion management port init */ 329 void ecore_init_cmng(const struct cmng_init_input *input_data, 330 struct cmng_init *ram_data) 331 { 332 u32_t r_param; 333 mm_mem_zero(ram_data,sizeof(struct cmng_init)); 334 335 ram_data->port.flags = input_data->flags; 336 337 /* 338 * number of bytes transmitted in a rate of 10Gbps 339 * in one usec = 1.25KB. 340 */ 341 r_param = BITS_TO_BYTES(input_data->port_rate); 342 ecore_init_max(input_data, r_param, ram_data); 343 ecore_init_min(input_data, r_param, ram_data); 344 ecore_init_fw_wrr(input_data, r_param, ram_data); 345 ecore_init_safc(input_data, ram_data); 346 } 347 348