1255736Sdavidch/*- 2255736Sdavidch * Copyright (c) 2007-2013 Broadcom Corporation. All rights reserved. 3255736Sdavidch * 4255736Sdavidch * Eric Davis <edavis@broadcom.com> 5255736Sdavidch * David Christensen <davidch@broadcom.com> 6255736Sdavidch * Gary Zambrano <zambrano@broadcom.com> 7255736Sdavidch * 8255736Sdavidch * Redistribution and use in source and binary forms, with or without 9255736Sdavidch * modification, are permitted provided that the following conditions 10255736Sdavidch * are met: 11255736Sdavidch * 12255736Sdavidch * 1. Redistributions of source code must retain the above copyright 13255736Sdavidch * notice, this list of conditions and the following disclaimer. 14255736Sdavidch * 2. Redistributions in binary form must reproduce the above copyright 15255736Sdavidch * notice, this list of conditions and the following disclaimer in the 16255736Sdavidch * documentation and/or other materials provided with the distribution. 17255736Sdavidch * 3. Neither the name of Broadcom Corporation nor the name of its contributors 18255736Sdavidch * may be used to endorse or promote products derived from this software 19255736Sdavidch * without specific prior written consent. 20255736Sdavidch * 21255736Sdavidch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' 22255736Sdavidch * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23255736Sdavidch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24255736Sdavidch * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 25255736Sdavidch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26255736Sdavidch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27255736Sdavidch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28255736Sdavidch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29255736Sdavidch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30255736Sdavidch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31255736Sdavidch * THE POSSIBILITY OF SUCH DAMAGE. 32255736Sdavidch */ 33255736Sdavidch 34255736Sdavidch#include <sys/cdefs.h> 35255736Sdavidch__FBSDID("$FreeBSD$"); 36255736Sdavidch 37255736Sdavidch#ifndef ECORE_INIT_H 38255736Sdavidch#define ECORE_INIT_H 39255736Sdavidch 40255736Sdavidch/* Init operation types and structures */ 41255736Sdavidchenum { 42255736Sdavidch OP_RD = 0x1, /* read a single register */ 43255736Sdavidch OP_WR, /* write a single register */ 44255736Sdavidch OP_SW, /* copy a string to the device */ 45255736Sdavidch OP_ZR, /* clear memory */ 46255736Sdavidch OP_ZP, /* unzip then copy with DMAE */ 47255736Sdavidch OP_WR_64, /* write 64 bit pattern */ 48255736Sdavidch OP_WB, /* copy a string using DMAE */ 49255736Sdavidch#ifndef FW_ZIP_SUPPORT 50255736Sdavidch OP_FW, /* copy an array from fw data (only used with unzipped FW) */ 51255736Sdavidch#endif 52255736Sdavidch OP_WB_ZR, /* Clear a string using DMAE or indirect-wr */ 53255736Sdavidch OP_IF_MODE_OR, /* Skip the following ops if all init modes don't match */ 54255736Sdavidch OP_IF_MODE_AND, /* Skip the following ops if any init modes don't match */ 55255736Sdavidch OP_IF_PHASE, 56255736Sdavidch OP_RT, 57255736Sdavidch OP_DELAY, 58255736Sdavidch OP_VERIFY, 59255736Sdavidch OP_MAX 60255736Sdavidch}; 61255736Sdavidch 62255736Sdavidchenum { 63255736Sdavidch STAGE_START, 64255736Sdavidch STAGE_END, 65255736Sdavidch}; 66255736Sdavidch 67255736Sdavidch/* Returns the index of start or end of a specific block stage in ops array*/ 68255736Sdavidch#define BLOCK_OPS_IDX(block, stage, end) \ 69255736Sdavidch (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end)) 70255736Sdavidch 71255736Sdavidch 72255736Sdavidch/* structs for the various opcodes */ 73255736Sdavidchstruct raw_op { 74255736Sdavidch uint32_t op:8; 75255736Sdavidch uint32_t offset:24; 76255736Sdavidch uint32_t raw_data; 77255736Sdavidch}; 78255736Sdavidch 79255736Sdavidchstruct op_read { 80255736Sdavidch uint32_t op:8; 81255736Sdavidch uint32_t offset:24; 82255736Sdavidch uint32_t val; 83255736Sdavidch}; 84255736Sdavidch 85255736Sdavidchstruct op_write { 86255736Sdavidch uint32_t op:8; 87255736Sdavidch uint32_t offset:24; 88255736Sdavidch uint32_t val; 89255736Sdavidch}; 90255736Sdavidch 91255736Sdavidchstruct op_arr_write { 92255736Sdavidch uint32_t op:8; 93255736Sdavidch uint32_t offset:24; 94255736Sdavidch#ifdef __BIG_ENDIAN 95255736Sdavidch uint16_t data_len; 96255736Sdavidch uint16_t data_off; 97255736Sdavidch#else /* __LITTLE_ENDIAN */ 98255736Sdavidch uint16_t data_off; 99255736Sdavidch uint16_t data_len; 100255736Sdavidch#endif 101255736Sdavidch}; 102255736Sdavidch 103255736Sdavidchstruct op_zero { 104255736Sdavidch uint32_t op:8; 105255736Sdavidch uint32_t offset:24; 106255736Sdavidch uint32_t len; 107255736Sdavidch}; 108255736Sdavidch 109255736Sdavidchstruct op_if_mode { 110255736Sdavidch uint32_t op:8; 111255736Sdavidch uint32_t cmd_offset:24; 112255736Sdavidch uint32_t mode_bit_map; 113255736Sdavidch}; 114255736Sdavidch 115255736Sdavidchstruct op_if_phase { 116255736Sdavidch uint32_t op:8; 117255736Sdavidch uint32_t cmd_offset:24; 118255736Sdavidch uint32_t phase_bit_map; 119255736Sdavidch}; 120255736Sdavidch 121255736Sdavidchstruct op_delay { 122255736Sdavidch uint32_t op:8; 123255736Sdavidch uint32_t reserved:24; 124255736Sdavidch uint32_t delay; 125255736Sdavidch}; 126255736Sdavidch 127255736Sdavidchunion init_op { 128255736Sdavidch struct op_read read; 129255736Sdavidch struct op_write write; 130255736Sdavidch struct op_arr_write arr_wr; 131255736Sdavidch struct op_zero zero; 132255736Sdavidch struct raw_op raw; 133255736Sdavidch struct op_if_mode if_mode; 134255736Sdavidch struct op_if_phase if_phase; 135255736Sdavidch struct op_delay delay; 136255736Sdavidch}; 137255736Sdavidch 138255736Sdavidch 139255736Sdavidch/* Init Phases */ 140255736Sdavidchenum { 141255736Sdavidch PHASE_COMMON, 142255736Sdavidch PHASE_PORT0, 143255736Sdavidch PHASE_PORT1, 144255736Sdavidch PHASE_PF0, 145255736Sdavidch PHASE_PF1, 146255736Sdavidch PHASE_PF2, 147255736Sdavidch PHASE_PF3, 148255736Sdavidch PHASE_PF4, 149255736Sdavidch PHASE_PF5, 150255736Sdavidch PHASE_PF6, 151255736Sdavidch PHASE_PF7, 152255736Sdavidch NUM_OF_INIT_PHASES 153255736Sdavidch}; 154255736Sdavidch 155255736Sdavidch/* Init Modes */ 156255736Sdavidchenum { 157255736Sdavidch MODE_ASIC = 0x00000001, 158255736Sdavidch MODE_FPGA = 0x00000002, 159255736Sdavidch MODE_EMUL = 0x00000004, 160255736Sdavidch MODE_E2 = 0x00000008, 161255736Sdavidch MODE_E3 = 0x00000010, 162255736Sdavidch MODE_PORT2 = 0x00000020, 163255736Sdavidch MODE_PORT4 = 0x00000040, 164255736Sdavidch MODE_SF = 0x00000080, 165255736Sdavidch MODE_MF = 0x00000100, 166255736Sdavidch MODE_MF_SD = 0x00000200, 167255736Sdavidch MODE_MF_SI = 0x00000400, 168255736Sdavidch MODE_MF_AFEX = 0x00000800, 169255736Sdavidch MODE_E3_A0 = 0x00001000, 170255736Sdavidch MODE_E3_B0 = 0x00002000, 171255736Sdavidch MODE_COS3 = 0x00004000, 172255736Sdavidch MODE_COS6 = 0x00008000, 173255736Sdavidch MODE_LITTLE_ENDIAN = 0x00010000, 174255736Sdavidch MODE_BIG_ENDIAN = 0x00020000, 175255736Sdavidch}; 176255736Sdavidch 177255736Sdavidch/* Init Blocks */ 178255736Sdavidchenum { 179255736Sdavidch BLOCK_ATC, 180255736Sdavidch BLOCK_BRB1, 181255736Sdavidch BLOCK_CCM, 182255736Sdavidch BLOCK_CDU, 183255736Sdavidch BLOCK_CFC, 184255736Sdavidch BLOCK_CSDM, 185255736Sdavidch BLOCK_CSEM, 186255736Sdavidch BLOCK_DBG, 187255736Sdavidch BLOCK_DMAE, 188255736Sdavidch BLOCK_DORQ, 189255736Sdavidch BLOCK_HC, 190255736Sdavidch BLOCK_IGU, 191255736Sdavidch BLOCK_MISC, 192255736Sdavidch BLOCK_NIG, 193255736Sdavidch BLOCK_PBF, 194255736Sdavidch BLOCK_PGLUE_B, 195255736Sdavidch BLOCK_PRS, 196255736Sdavidch BLOCK_PXP2, 197255736Sdavidch BLOCK_PXP, 198255736Sdavidch BLOCK_QM, 199255736Sdavidch BLOCK_SRC, 200255736Sdavidch BLOCK_TCM, 201255736Sdavidch BLOCK_TM, 202255736Sdavidch BLOCK_TSDM, 203255736Sdavidch BLOCK_TSEM, 204255736Sdavidch BLOCK_UCM, 205255736Sdavidch BLOCK_UPB, 206255736Sdavidch BLOCK_USDM, 207255736Sdavidch BLOCK_USEM, 208255736Sdavidch BLOCK_XCM, 209255736Sdavidch BLOCK_XPB, 210255736Sdavidch BLOCK_XSDM, 211255736Sdavidch BLOCK_XSEM, 212255736Sdavidch BLOCK_MISC_AEU, 213255736Sdavidch NUM_OF_INIT_BLOCKS 214255736Sdavidch}; 215255736Sdavidch 216255736Sdavidch 217255736Sdavidch 218255736Sdavidch 219255736Sdavidch 220255736Sdavidch 221255736Sdavidch 222255736Sdavidch 223255736Sdavidch/* Vnics per mode */ 224255736Sdavidch#define ECORE_PORT2_MODE_NUM_VNICS 4 225255736Sdavidch 226255736Sdavidch 227255736Sdavidch/* QM queue numbers */ 228255736Sdavidch#define ECORE_ETH_Q 0 229255736Sdavidch#define ECORE_TOE_Q 3 230255736Sdavidch#define ECORE_TOE_ACK_Q 6 231255736Sdavidch#define ECORE_ISCSI_Q 9 232255736Sdavidch#define ECORE_ISCSI_ACK_Q 11 233255736Sdavidch#define ECORE_FCOE_Q 10 234255736Sdavidch 235255736Sdavidch/* Vnics per mode */ 236255736Sdavidch#define ECORE_PORT4_MODE_NUM_VNICS 2 237255736Sdavidch 238255736Sdavidch/* COS offset for port1 in E3 B0 4port mode */ 239255736Sdavidch#define ECORE_E3B0_PORT1_COS_OFFSET 3 240255736Sdavidch 241255736Sdavidch/* QM Register addresses */ 242255736Sdavidch#define ECORE_Q_VOQ_REG_ADDR(pf_q_num)\ 243255736Sdavidch (QM_REG_QVOQIDX_0 + 4 * (pf_q_num)) 244255736Sdavidch#define ECORE_VOQ_Q_REG_ADDR(cos, pf_q_num)\ 245255736Sdavidch (QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5))) 246255736Sdavidch#define ECORE_Q_CMDQ_REG_ADDR(pf_q_num)\ 247255736Sdavidch (QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4)) 248255736Sdavidch 249255736Sdavidch/* extracts the QM queue number for the specified port and vnic */ 250255736Sdavidch#define ECORE_PF_Q_NUM(q_num, port, vnic)\ 251255736Sdavidch ((((port) << 1) | (vnic)) * 16 + (q_num)) 252255736Sdavidch 253255736Sdavidch 254255736Sdavidch/* Maps the specified queue to the specified COS */ 255255736Sdavidchstatic inline void ecore_map_q_cos(struct bxe_softc *sc, uint32_t q_num, uint32_t new_cos) 256255736Sdavidch{ 257255736Sdavidch /* find current COS mapping */ 258255736Sdavidch uint32_t curr_cos = REG_RD(sc, QM_REG_QVOQIDX_0 + q_num * 4); 259255736Sdavidch 260255736Sdavidch /* check if queue->COS mapping has changed */ 261255736Sdavidch if (curr_cos != new_cos) { 262255736Sdavidch uint32_t num_vnics = ECORE_PORT2_MODE_NUM_VNICS; 263255736Sdavidch uint32_t reg_addr, reg_bit_map, vnic; 264255736Sdavidch 265255736Sdavidch /* update parameters for 4port mode */ 266255736Sdavidch if (INIT_MODE_FLAGS(sc) & MODE_PORT4) { 267255736Sdavidch num_vnics = ECORE_PORT4_MODE_NUM_VNICS; 268255736Sdavidch if (PORT_ID(sc)) { 269255736Sdavidch curr_cos += ECORE_E3B0_PORT1_COS_OFFSET; 270255736Sdavidch new_cos += ECORE_E3B0_PORT1_COS_OFFSET; 271255736Sdavidch } 272255736Sdavidch } 273255736Sdavidch 274255736Sdavidch /* change queue mapping for each VNIC */ 275255736Sdavidch for (vnic = 0; vnic < num_vnics; vnic++) { 276255736Sdavidch uint32_t pf_q_num = 277255736Sdavidch ECORE_PF_Q_NUM(q_num, PORT_ID(sc), vnic); 278255736Sdavidch uint32_t q_bit_map = 1 << (pf_q_num & 0x1f); 279255736Sdavidch 280255736Sdavidch /* overwrite queue->VOQ mapping */ 281255736Sdavidch REG_WR(sc, ECORE_Q_VOQ_REG_ADDR(pf_q_num), new_cos); 282255736Sdavidch 283255736Sdavidch /* clear queue bit from current COS bit map */ 284255736Sdavidch reg_addr = ECORE_VOQ_Q_REG_ADDR(curr_cos, pf_q_num); 285255736Sdavidch reg_bit_map = REG_RD(sc, reg_addr); 286255736Sdavidch REG_WR(sc, reg_addr, reg_bit_map & (~q_bit_map)); 287255736Sdavidch 288255736Sdavidch /* set queue bit in new COS bit map */ 289255736Sdavidch reg_addr = ECORE_VOQ_Q_REG_ADDR(new_cos, pf_q_num); 290255736Sdavidch reg_bit_map = REG_RD(sc, reg_addr); 291255736Sdavidch REG_WR(sc, reg_addr, reg_bit_map | q_bit_map); 292255736Sdavidch 293255736Sdavidch /* set/clear queue bit in command-queue bit map 294255736Sdavidch (E2/E3A0 only, valid COS values are 0/1) */ 295255736Sdavidch if (!(INIT_MODE_FLAGS(sc) & MODE_E3_B0)) { 296255736Sdavidch reg_addr = ECORE_Q_CMDQ_REG_ADDR(pf_q_num); 297255736Sdavidch reg_bit_map = REG_RD(sc, reg_addr); 298255736Sdavidch q_bit_map = 1 << (2 * (pf_q_num & 0xf)); 299255736Sdavidch reg_bit_map = new_cos ? 300255736Sdavidch (reg_bit_map | q_bit_map) : 301255736Sdavidch (reg_bit_map & (~q_bit_map)); 302255736Sdavidch REG_WR(sc, reg_addr, reg_bit_map); 303255736Sdavidch } 304255736Sdavidch } 305255736Sdavidch } 306255736Sdavidch} 307255736Sdavidch 308255736Sdavidch/* Configures the QM according to the specified per-traffic-type COSes */ 309255736Sdavidchstatic inline void ecore_dcb_config_qm(struct bxe_softc *sc, enum cos_mode mode, 310255736Sdavidch struct priority_cos *traffic_cos) 311255736Sdavidch{ 312255736Sdavidch ecore_map_q_cos(sc, ECORE_FCOE_Q, 313255736Sdavidch traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos); 314255736Sdavidch ecore_map_q_cos(sc, ECORE_ISCSI_Q, 315255736Sdavidch traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); 316255736Sdavidch ecore_map_q_cos(sc, ECORE_ISCSI_ACK_Q, 317255736Sdavidch traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); 318255736Sdavidch if (mode != STATIC_COS) { 319255736Sdavidch /* required only in OVERRIDE_COS mode */ 320255736Sdavidch ecore_map_q_cos(sc, ECORE_ETH_Q, 321255736Sdavidch traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); 322255736Sdavidch ecore_map_q_cos(sc, ECORE_TOE_Q, 323255736Sdavidch traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); 324255736Sdavidch ecore_map_q_cos(sc, ECORE_TOE_ACK_Q, 325255736Sdavidch traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); 326255736Sdavidch } 327255736Sdavidch} 328255736Sdavidch 329255736Sdavidch 330255736Sdavidch/* 331255736Sdavidch * congestion managment port init api description 332255736Sdavidch * the api works as follows: 333255736Sdavidch * the driver should pass the cmng_init_input struct, the port_init function 334255736Sdavidch * will prepare the required internal ram structure which will be passed back 335255736Sdavidch * to the driver (cmng_init) that will write it into the internal ram. 336255736Sdavidch * 337255736Sdavidch * IMPORTANT REMARKS: 338255736Sdavidch * 1. the cmng_init struct does not represent the contiguous internal ram 339255736Sdavidch * structure. the driver should use the XSTORM_CMNG_PERPORT_VARS_OFFSET 340255736Sdavidch * offset in order to write the port sub struct and the 341255736Sdavidch * PFID_FROM_PORT_AND_VNIC offset for writing the vnic sub struct (in other 342255736Sdavidch * words - don't use memcpy!). 343255736Sdavidch * 2. although the cmng_init struct is filled for the maximal vnic number 344255736Sdavidch * possible, the driver should only write the valid vnics into the internal 345255736Sdavidch * ram according to the appropriate port mode. 346255736Sdavidch */ 347255736Sdavidch#define BITS_TO_BYTES(x) ((x)/8) 348255736Sdavidch 349255736Sdavidch/* CMNG constants, as derived from system spec calculations */ 350255736Sdavidch 351255736Sdavidch/* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */ 352255736Sdavidch#define DEF_MIN_RATE 100 353255736Sdavidch 354255736Sdavidch/* resolution of the rate shaping timer - 400 usec */ 355255736Sdavidch#define RS_PERIODIC_TIMEOUT_USEC 400 356255736Sdavidch 357255736Sdavidch/* 358255736Sdavidch * number of bytes in single QM arbitration cycle - 359255736Sdavidch * coefficient for calculating the fairness timer 360255736Sdavidch */ 361255736Sdavidch#define QM_ARB_BYTES 160000 362255736Sdavidch 363255736Sdavidch/* resolution of Min algorithm 1:100 */ 364255736Sdavidch#define MIN_RES 100 365255736Sdavidch 366255736Sdavidch/* 367255736Sdavidch * how many bytes above threshold for 368255736Sdavidch * the minimal credit of Min algorithm 369255736Sdavidch */ 370255736Sdavidch#define MIN_ABOVE_THRESH 32768 371255736Sdavidch 372255736Sdavidch/* 373255736Sdavidch * Fairness algorithm integration time coefficient - 374255736Sdavidch * for calculating the actual Tfair 375255736Sdavidch */ 376255736Sdavidch#define T_FAIR_COEF ((MIN_ABOVE_THRESH + QM_ARB_BYTES) * 8 * MIN_RES) 377255736Sdavidch 378255736Sdavidch/* Memory of fairness algorithm - 2 cycles */ 379255736Sdavidch#define FAIR_MEM 2 380255736Sdavidch#define SAFC_TIMEOUT_USEC 52 381255736Sdavidch 382255736Sdavidch#define SDM_TICKS 4 383255736Sdavidch 384255736Sdavidch 385255736Sdavidchstatic inline void ecore_init_max(const struct cmng_init_input *input_data, 386255736Sdavidch uint32_t r_param, struct cmng_init *ram_data) 387255736Sdavidch{ 388255736Sdavidch uint32_t vnic; 389255736Sdavidch struct cmng_vnic *vdata = &ram_data->vnic; 390255736Sdavidch struct cmng_struct_per_port *pdata = &ram_data->port; 391255736Sdavidch /* 392255736Sdavidch * rate shaping per-port variables 393255736Sdavidch * 100 micro seconds in SDM ticks = 25 394255736Sdavidch * since each tick is 4 microSeconds 395255736Sdavidch */ 396255736Sdavidch 397255736Sdavidch pdata->rs_vars.rs_periodic_timeout = 398255736Sdavidch RS_PERIODIC_TIMEOUT_USEC / SDM_TICKS; 399255736Sdavidch 400255736Sdavidch /* this is the threshold below which no timer arming will occur. 401255736Sdavidch * 1.25 coefficient is for the threshold to be a little bigger 402255736Sdavidch * then the real time to compensate for timer in-accuracy 403255736Sdavidch */ 404255736Sdavidch pdata->rs_vars.rs_threshold = 405255736Sdavidch (5 * RS_PERIODIC_TIMEOUT_USEC * r_param)/4; 406255736Sdavidch 407255736Sdavidch /* rate shaping per-vnic variables */ 408255736Sdavidch for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) { 409255736Sdavidch /* global vnic counter */ 410255736Sdavidch vdata->vnic_max_rate[vnic].vn_counter.rate = 411255736Sdavidch input_data->vnic_max_rate[vnic]; 412255736Sdavidch /* 413255736Sdavidch * maximal Mbps for this vnic 414255736Sdavidch * the quota in each timer period - number of bytes 415255736Sdavidch * transmitted in this period 416255736Sdavidch */ 417255736Sdavidch vdata->vnic_max_rate[vnic].vn_counter.quota = 418255736Sdavidch RS_PERIODIC_TIMEOUT_USEC * 419255736Sdavidch (uint32_t)vdata->vnic_max_rate[vnic].vn_counter.rate / 8; 420255736Sdavidch } 421255736Sdavidch 422255736Sdavidch} 423255736Sdavidch 424255736Sdavidchstatic inline void ecore_init_max_per_vn(uint16_t vnic_max_rate, 425255736Sdavidch struct rate_shaping_vars_per_vn *ram_data) 426255736Sdavidch{ 427255736Sdavidch /* global vnic counter */ 428255736Sdavidch ram_data->vn_counter.rate = vnic_max_rate; 429255736Sdavidch 430255736Sdavidch /* 431255736Sdavidch * maximal Mbps for this vnic 432255736Sdavidch * the quota in each timer period - number of bytes 433255736Sdavidch * transmitted in this period 434255736Sdavidch */ 435255736Sdavidch ram_data->vn_counter.quota = 436255736Sdavidch RS_PERIODIC_TIMEOUT_USEC * (uint32_t)vnic_max_rate / 8; 437255736Sdavidch} 438255736Sdavidch 439255736Sdavidchstatic inline void ecore_init_min(const struct cmng_init_input *input_data, 440255736Sdavidch uint32_t r_param, struct cmng_init *ram_data) 441255736Sdavidch{ 442255736Sdavidch uint32_t vnic, fair_periodic_timeout_usec, vnicWeightSum, tFair; 443255736Sdavidch struct cmng_vnic *vdata = &ram_data->vnic; 444255736Sdavidch struct cmng_struct_per_port *pdata = &ram_data->port; 445255736Sdavidch 446255736Sdavidch /* this is the resolution of the fairness timer */ 447255736Sdavidch fair_periodic_timeout_usec = QM_ARB_BYTES / r_param; 448255736Sdavidch 449255736Sdavidch /* 450255736Sdavidch * fairness per-port variables 451255736Sdavidch * for 10G it is 1000usec. for 1G it is 10000usec. 452255736Sdavidch */ 453255736Sdavidch tFair = T_FAIR_COEF / input_data->port_rate; 454255736Sdavidch 455255736Sdavidch /* this is the threshold below which we won't arm the timer anymore */ 456255736Sdavidch pdata->fair_vars.fair_threshold = QM_ARB_BYTES; 457255736Sdavidch 458255736Sdavidch /* 459255736Sdavidch * we multiply by 1e3/8 to get bytes/msec. We don't want the credits 460255736Sdavidch * to pass a credit of the T_FAIR*FAIR_MEM (algorithm resolution) 461255736Sdavidch */ 462255736Sdavidch pdata->fair_vars.upper_bound = r_param * tFair * FAIR_MEM; 463255736Sdavidch 464255736Sdavidch /* since each tick is 4 microSeconds */ 465255736Sdavidch pdata->fair_vars.fairness_timeout = 466255736Sdavidch fair_periodic_timeout_usec / SDM_TICKS; 467255736Sdavidch 468255736Sdavidch /* calculate sum of weights */ 469255736Sdavidch vnicWeightSum = 0; 470255736Sdavidch 471255736Sdavidch for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) 472255736Sdavidch vnicWeightSum += input_data->vnic_min_rate[vnic]; 473255736Sdavidch 474255736Sdavidch /* global vnic counter */ 475255736Sdavidch if (vnicWeightSum > 0) { 476255736Sdavidch /* fairness per-vnic variables */ 477255736Sdavidch for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) { 478255736Sdavidch /* 479255736Sdavidch * this is the credit for each period of the fairness 480255736Sdavidch * algorithm - number of bytes in T_FAIR (this vnic 481255736Sdavidch * share of the port rate) 482255736Sdavidch */ 483255736Sdavidch vdata->vnic_min_rate[vnic].vn_credit_delta = 484255736Sdavidch ((uint32_t)(input_data->vnic_min_rate[vnic]) * 100 * 485255736Sdavidch (T_FAIR_COEF / (8 * 100 * vnicWeightSum))); 486255736Sdavidch if (vdata->vnic_min_rate[vnic].vn_credit_delta < 487255736Sdavidch pdata->fair_vars.fair_threshold + 488255736Sdavidch MIN_ABOVE_THRESH) { 489255736Sdavidch vdata->vnic_min_rate[vnic].vn_credit_delta = 490255736Sdavidch pdata->fair_vars.fair_threshold + 491255736Sdavidch MIN_ABOVE_THRESH; 492255736Sdavidch } 493255736Sdavidch } 494255736Sdavidch } 495255736Sdavidch} 496255736Sdavidch 497255736Sdavidchstatic inline void ecore_init_fw_wrr(const struct cmng_init_input *input_data, 498255736Sdavidch uint32_t r_param, struct cmng_init *ram_data) 499255736Sdavidch{ 500255736Sdavidch uint32_t vnic, cos; 501255736Sdavidch uint32_t cosWeightSum = 0; 502255736Sdavidch struct cmng_vnic *vdata = &ram_data->vnic; 503255736Sdavidch struct cmng_struct_per_port *pdata = &ram_data->port; 504255736Sdavidch 505255736Sdavidch for (cos = 0; cos < MAX_COS_NUMBER; cos++) 506255736Sdavidch cosWeightSum += input_data->cos_min_rate[cos]; 507255736Sdavidch 508255736Sdavidch if (cosWeightSum > 0) { 509255736Sdavidch 510255736Sdavidch for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) { 511255736Sdavidch /* 512255736Sdavidch * Since cos and vnic shouldn't work together the rate 513255736Sdavidch * to divide between the coses is the port rate. 514255736Sdavidch */ 515255736Sdavidch uint32_t *ccd = vdata->vnic_min_rate[vnic].cos_credit_delta; 516255736Sdavidch for (cos = 0; cos < MAX_COS_NUMBER; cos++) { 517255736Sdavidch /* 518255736Sdavidch * this is the credit for each period of 519255736Sdavidch * the fairness algorithm - number of bytes 520255736Sdavidch * in T_FAIR (this cos share of the vnic rate) 521255736Sdavidch */ 522255736Sdavidch ccd[cos] = 523255736Sdavidch ((uint32_t)input_data->cos_min_rate[cos] * 100 * 524255736Sdavidch (T_FAIR_COEF / (8 * 100 * cosWeightSum))); 525255736Sdavidch if (ccd[cos] < pdata->fair_vars.fair_threshold 526255736Sdavidch + MIN_ABOVE_THRESH) { 527255736Sdavidch ccd[cos] = 528255736Sdavidch pdata->fair_vars.fair_threshold + 529255736Sdavidch MIN_ABOVE_THRESH; 530255736Sdavidch } 531255736Sdavidch } 532255736Sdavidch } 533255736Sdavidch } 534255736Sdavidch} 535255736Sdavidch 536255736Sdavidchstatic inline void ecore_init_safc(const struct cmng_init_input *input_data, 537255736Sdavidch struct cmng_init *ram_data) 538255736Sdavidch{ 539255736Sdavidch /* in microSeconds */ 540255736Sdavidch ram_data->port.safc_vars.safc_timeout_usec = SAFC_TIMEOUT_USEC; 541255736Sdavidch} 542255736Sdavidch 543255736Sdavidch/* Congestion management port init */ 544255736Sdavidchstatic inline void ecore_init_cmng(const struct cmng_init_input *input_data, 545255736Sdavidch struct cmng_init *ram_data) 546255736Sdavidch{ 547255736Sdavidch uint32_t r_param; 548255736Sdavidch ECORE_MEMSET(ram_data, 0,sizeof(struct cmng_init)); 549255736Sdavidch 550255736Sdavidch ram_data->port.flags = input_data->flags; 551255736Sdavidch 552255736Sdavidch /* 553255736Sdavidch * number of bytes transmitted in a rate of 10Gbps 554255736Sdavidch * in one usec = 1.25KB. 555255736Sdavidch */ 556255736Sdavidch r_param = BITS_TO_BYTES(input_data->port_rate); 557255736Sdavidch ecore_init_max(input_data, r_param, ram_data); 558255736Sdavidch ecore_init_min(input_data, r_param, ram_data); 559255736Sdavidch ecore_init_fw_wrr(input_data, r_param, ram_data); 560255736Sdavidch ecore_init_safc(input_data, ram_data); 561255736Sdavidch} 562255736Sdavidch 563255736Sdavidch 564255736Sdavidch 565255736Sdavidch 566255736Sdavidch/* Returns the index of start or end of a specific block stage in ops array*/ 567255736Sdavidch#define BLOCK_OPS_IDX(block, stage, end) \ 568255736Sdavidch (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end)) 569255736Sdavidch 570255736Sdavidch 571255736Sdavidch#define INITOP_SET 0 /* set the HW directly */ 572255736Sdavidch#define INITOP_CLEAR 1 /* clear the HW directly */ 573255736Sdavidch#define INITOP_INIT 2 /* set the init-value array */ 574255736Sdavidch 575255736Sdavidch/**************************************************************************** 576255736Sdavidch* ILT management 577255736Sdavidch****************************************************************************/ 578255736Sdavidchstruct ilt_line { 579255736Sdavidch ecore_dma_addr_t page_mapping; 580255736Sdavidch void *page; 581255736Sdavidch uint32_t size; 582255736Sdavidch}; 583255736Sdavidch 584255736Sdavidchstruct ilt_client_info { 585255736Sdavidch uint32_t page_size; 586255736Sdavidch uint16_t start; 587255736Sdavidch uint16_t end; 588255736Sdavidch uint16_t client_num; 589255736Sdavidch uint16_t flags; 590255736Sdavidch#define ILT_CLIENT_SKIP_INIT 0x1 591255736Sdavidch#define ILT_CLIENT_SKIP_MEM 0x2 592255736Sdavidch}; 593255736Sdavidch 594255736Sdavidchstruct ecore_ilt { 595255736Sdavidch uint32_t start_line; 596255736Sdavidch struct ilt_line *lines; 597255736Sdavidch struct ilt_client_info clients[4]; 598255736Sdavidch#define ILT_CLIENT_CDU 0 599255736Sdavidch#define ILT_CLIENT_QM 1 600255736Sdavidch#define ILT_CLIENT_SRC 2 601255736Sdavidch#define ILT_CLIENT_TM 3 602255736Sdavidch}; 603255736Sdavidch 604255736Sdavidch/**************************************************************************** 605255736Sdavidch* SRC configuration 606255736Sdavidch****************************************************************************/ 607255736Sdavidchstruct src_ent { 608255736Sdavidch uint8_t opaque[56]; 609255736Sdavidch uint64_t next; 610255736Sdavidch}; 611255736Sdavidch 612255736Sdavidch/**************************************************************************** 613255736Sdavidch* Parity configuration 614255736Sdavidch****************************************************************************/ 615255736Sdavidch#define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2, m3) \ 616255736Sdavidch{ \ 617255736Sdavidch block##_REG_##block##_PRTY_MASK, \ 618255736Sdavidch block##_REG_##block##_PRTY_STS_CLR, \ 619255736Sdavidch en_mask, {m1, m1h, m2, m3}, #block \ 620255736Sdavidch} 621255736Sdavidch 622255736Sdavidch#define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2, m3) \ 623255736Sdavidch{ \ 624255736Sdavidch block##_REG_##block##_PRTY_MASK_0, \ 625255736Sdavidch block##_REG_##block##_PRTY_STS_CLR_0, \ 626255736Sdavidch en_mask, {m1, m1h, m2, m3}, #block"_0" \ 627255736Sdavidch} 628255736Sdavidch 629255736Sdavidch#define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2, m3) \ 630255736Sdavidch{ \ 631255736Sdavidch block##_REG_##block##_PRTY_MASK_1, \ 632255736Sdavidch block##_REG_##block##_PRTY_STS_CLR_1, \ 633255736Sdavidch en_mask, {m1, m1h, m2, m3}, #block"_1" \ 634255736Sdavidch} 635255736Sdavidch 636255736Sdavidchstatic const struct { 637255736Sdavidch uint32_t mask_addr; 638255736Sdavidch uint32_t sts_clr_addr; 639255736Sdavidch uint32_t en_mask; /* Mask to enable parity attentions */ 640255736Sdavidch struct { 641255736Sdavidch uint32_t e1; /* 57710 */ 642255736Sdavidch uint32_t e1h; /* 57711 */ 643255736Sdavidch uint32_t e2; /* 57712 */ 644255736Sdavidch uint32_t e3; /* 578xx */ 645255736Sdavidch } reg_mask; /* Register mask (all valid bits) */ 646255736Sdavidch char name[8]; /* Block's longest name is 7 characters long 647255736Sdavidch * (name + suffix) 648255736Sdavidch */ 649255736Sdavidch} ecore_blocks_parity_data[] = { 650255736Sdavidch /* bit 19 masked */ 651255736Sdavidch /* REG_WR(bp, PXP_REG_PXP_PRTY_MASK, 0x80000); */ 652255736Sdavidch /* bit 5,18,20-31 */ 653255736Sdavidch /* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_0, 0xfff40020); */ 654255736Sdavidch /* bit 5 */ 655255736Sdavidch /* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_1, 0x20); */ 656255736Sdavidch /* REG_WR(bp, HC_REG_HC_PRTY_MASK, 0x0); */ 657255736Sdavidch /* REG_WR(bp, MISC_REG_MISC_PRTY_MASK, 0x0); */ 658255736Sdavidch 659255736Sdavidch /* Block IGU, MISC, PXP and PXP2 parity errors as long as we don't 660255736Sdavidch * want to handle "system kill" flow at the moment. 661255736Sdavidch */ 662255736Sdavidch BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x3ffffff, 0x7ffffff, 663255736Sdavidch 0x7ffffff), 664255736Sdavidch BLOCK_PRTY_INFO_0(PXP2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 665255736Sdavidch 0xffffffff), 666255736Sdavidch BLOCK_PRTY_INFO_1(PXP2, 0x1ffffff, 0x7f, 0x7f, 0x7ff, 0x1ffffff), 667255736Sdavidch BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0, 0), 668255736Sdavidch BLOCK_PRTY_INFO(NIG, 0xffffffff, 0x3fffffff, 0xffffffff, 0, 0), 669255736Sdavidch BLOCK_PRTY_INFO_0(NIG, 0xffffffff, 0, 0, 0xffffffff, 0xffffffff), 670255736Sdavidch BLOCK_PRTY_INFO_1(NIG, 0xffff, 0, 0, 0xff, 0xffff), 671255736Sdavidch BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff, 0x7ff), 672255736Sdavidch BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1, 0x1), 673255736Sdavidch BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff, 0xfff), 674255736Sdavidch BLOCK_PRTY_INFO(ATC, 0x1f, 0, 0, 0x1f, 0x1f), 675255736Sdavidch BLOCK_PRTY_INFO(PGLUE_B, 0x3, 0, 0, 0x3, 0x3), 676255736Sdavidch BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3, 0x3), 677255736Sdavidch {GRCBASE_UPB + PB_REG_PB_PRTY_MASK, 678255736Sdavidch GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0xf, 679255736Sdavidch {0xf, 0xf, 0xf, 0xf}, "UPB"}, 680255736Sdavidch {GRCBASE_XPB + PB_REG_PB_PRTY_MASK, 681255736Sdavidch GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0, 682255736Sdavidch {0xf, 0xf, 0xf, 0xf}, "XPB"}, 683255736Sdavidch BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7, 0x7), 684255736Sdavidch BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f, 0x1f), 685255736Sdavidch BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0xf, 0x3f), 686255736Sdavidch BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1, 0x1), 687255736Sdavidch BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf, 0xf), 688255736Sdavidch BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf, 0xf), 689255736Sdavidch BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff, 0xff), 690255736Sdavidch BLOCK_PRTY_INFO(PBF, 0, 0, 0x3ffff, 0xfffff, 0xfffffff), 691255736Sdavidch BLOCK_PRTY_INFO(TM, 0, 0, 0x7f, 0x7f, 0x7f), 692255736Sdavidch BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff, 0x7ff), 693255736Sdavidch BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff), 694255736Sdavidch BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff, 0x7ff), 695255736Sdavidch BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff), 696255736Sdavidch BLOCK_PRTY_INFO(TCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff), 697255736Sdavidch BLOCK_PRTY_INFO(CCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff), 698255736Sdavidch BLOCK_PRTY_INFO(UCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff), 699255736Sdavidch BLOCK_PRTY_INFO(XCM, 0, 0, 0x3fffffff, 0x3fffffff, 0x3fffffff), 700255736Sdavidch BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff, 701255736Sdavidch 0xffffffff), 702255736Sdavidch BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f, 0x3f), 703255736Sdavidch BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff, 704255736Sdavidch 0xffffffff), 705255736Sdavidch BLOCK_PRTY_INFO_1(USEM, 0, 0x3, 0x1f, 0x1f, 0x1f), 706255736Sdavidch BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff, 707255736Sdavidch 0xffffffff), 708255736Sdavidch BLOCK_PRTY_INFO_1(CSEM, 0, 0x3, 0x1f, 0x1f, 0x1f), 709255736Sdavidch BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff, 710255736Sdavidch 0xffffffff), 711255736Sdavidch BLOCK_PRTY_INFO_1(XSEM, 0, 0x3, 0x1f, 0x3f, 0x3f), 712255736Sdavidch}; 713255736Sdavidch 714255736Sdavidch 715255736Sdavidch/* [28] MCP Latched rom_parity 716255736Sdavidch * [29] MCP Latched ump_rx_parity 717255736Sdavidch * [30] MCP Latched ump_tx_parity 718255736Sdavidch * [31] MCP Latched scpad_parity 719255736Sdavidch */ 720258203Sedavis#define MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS \ 721255736Sdavidch (AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \ 722255736Sdavidch AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \ 723258203Sedavis AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY) 724258203Sedavis 725258203Sedavis#define MISC_AEU_ENABLE_MCP_PRTY_BITS \ 726258203Sedavis (MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS | \ 727255736Sdavidch AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY) 728255736Sdavidch 729255736Sdavidch/* Below registers control the MCP parity attention output. When 730255736Sdavidch * MISC_AEU_ENABLE_MCP_PRTY_BITS are set - attentions are 731255736Sdavidch * enabled, when cleared - disabled. 732255736Sdavidch */ 733258203Sedavisstatic const struct { 734258203Sedavis uint32_t addr; 735258203Sedavis uint32_t bits; 736258203Sedavis} mcp_attn_ctl_regs[] = { 737258203Sedavis { MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0, 738258203Sedavis MISC_AEU_ENABLE_MCP_PRTY_BITS }, 739258203Sedavis { MISC_REG_AEU_ENABLE4_NIG_0, 740258203Sedavis MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS }, 741258203Sedavis { MISC_REG_AEU_ENABLE4_PXP_0, 742258203Sedavis MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS }, 743258203Sedavis { MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0, 744258203Sedavis MISC_AEU_ENABLE_MCP_PRTY_BITS }, 745258203Sedavis { MISC_REG_AEU_ENABLE4_NIG_1, 746258203Sedavis MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS }, 747258203Sedavis { MISC_REG_AEU_ENABLE4_PXP_1, 748258203Sedavis MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS } 749255736Sdavidch}; 750255736Sdavidch 751255736Sdavidchstatic inline void ecore_set_mcp_parity(struct bxe_softc *sc, uint8_t enable) 752255736Sdavidch{ 753255736Sdavidch int i; 754255736Sdavidch uint32_t reg_val; 755255736Sdavidch 756255736Sdavidch for (i = 0; i < ARRSIZE(mcp_attn_ctl_regs); i++) { 757258203Sedavis reg_val = REG_RD(sc, mcp_attn_ctl_regs[i].addr); 758255736Sdavidch 759255736Sdavidch if (enable) 760258203Sedavis reg_val |= MISC_AEU_ENABLE_MCP_PRTY_BITS; /* Linux is using mcp_attn_ctl_regs[i].bits */ 761255736Sdavidch else 762258203Sedavis reg_val &= ~MISC_AEU_ENABLE_MCP_PRTY_BITS; /* Linux is using mcp_attn_ctl_regs[i].bits */ 763255736Sdavidch 764258203Sedavis REG_WR(sc, mcp_attn_ctl_regs[i].addr, reg_val); 765255736Sdavidch } 766255736Sdavidch} 767255736Sdavidch 768255736Sdavidchstatic inline uint32_t ecore_parity_reg_mask(struct bxe_softc *sc, int idx) 769255736Sdavidch{ 770255736Sdavidch if (CHIP_IS_E1(sc)) 771255736Sdavidch return ecore_blocks_parity_data[idx].reg_mask.e1; 772255736Sdavidch else if (CHIP_IS_E1H(sc)) 773255736Sdavidch return ecore_blocks_parity_data[idx].reg_mask.e1h; 774255736Sdavidch else if (CHIP_IS_E2(sc)) 775255736Sdavidch return ecore_blocks_parity_data[idx].reg_mask.e2; 776255736Sdavidch else /* CHIP_IS_E3 */ 777255736Sdavidch return ecore_blocks_parity_data[idx].reg_mask.e3; 778255736Sdavidch} 779255736Sdavidch 780255736Sdavidchstatic inline void ecore_disable_blocks_parity(struct bxe_softc *sc) 781255736Sdavidch{ 782255736Sdavidch int i; 783255736Sdavidch 784255736Sdavidch for (i = 0; i < ARRSIZE(ecore_blocks_parity_data); i++) { 785255736Sdavidch uint32_t dis_mask = ecore_parity_reg_mask(sc, i); 786255736Sdavidch 787255736Sdavidch if (dis_mask) { 788255736Sdavidch REG_WR(sc, ecore_blocks_parity_data[i].mask_addr, 789255736Sdavidch dis_mask); 790255736Sdavidch ECORE_MSG(sc, "Setting parity mask " 791255736Sdavidch "for %s to\t\t0x%x\n", 792255736Sdavidch ecore_blocks_parity_data[i].name, dis_mask); 793255736Sdavidch } 794255736Sdavidch } 795255736Sdavidch 796255736Sdavidch /* Disable MCP parity attentions */ 797255736Sdavidch ecore_set_mcp_parity(sc, FALSE); 798255736Sdavidch} 799255736Sdavidch 800255736Sdavidch/** 801255736Sdavidch * Clear the parity error status registers. 802255736Sdavidch */ 803255736Sdavidchstatic inline void ecore_clear_blocks_parity(struct bxe_softc *sc) 804255736Sdavidch{ 805255736Sdavidch int i; 806255736Sdavidch uint32_t reg_val, mcp_aeu_bits = 807255736Sdavidch AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | 808255736Sdavidch AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY | 809255736Sdavidch AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | 810255736Sdavidch AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY; 811255736Sdavidch 812255736Sdavidch /* Clear SEM_FAST parities */ 813255736Sdavidch REG_WR(sc, XSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); 814255736Sdavidch REG_WR(sc, TSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); 815255736Sdavidch REG_WR(sc, USEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); 816255736Sdavidch REG_WR(sc, CSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); 817255736Sdavidch 818255736Sdavidch for (i = 0; i < ARRSIZE(ecore_blocks_parity_data); i++) { 819255736Sdavidch uint32_t reg_mask = ecore_parity_reg_mask(sc, i); 820255736Sdavidch 821255736Sdavidch if (reg_mask) { 822255736Sdavidch reg_val = REG_RD(sc, ecore_blocks_parity_data[i]. 823255736Sdavidch sts_clr_addr); 824255736Sdavidch if (reg_val & reg_mask) 825255736Sdavidch ECORE_MSG(sc, 826255736Sdavidch "Parity errors in %s: 0x%x\n", 827255736Sdavidch ecore_blocks_parity_data[i].name, 828255736Sdavidch reg_val & reg_mask); 829255736Sdavidch } 830255736Sdavidch } 831255736Sdavidch 832255736Sdavidch /* Check if there were parity attentions in MCP */ 833255736Sdavidch reg_val = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_4_MCP); 834255736Sdavidch if (reg_val & mcp_aeu_bits) 835255736Sdavidch ECORE_MSG(sc, "Parity error in MCP: 0x%x\n", 836255736Sdavidch reg_val & mcp_aeu_bits); 837255736Sdavidch 838255736Sdavidch /* Clear parity attentions in MCP: 839255736Sdavidch * [7] clears Latched rom_parity 840255736Sdavidch * [8] clears Latched ump_rx_parity 841255736Sdavidch * [9] clears Latched ump_tx_parity 842255736Sdavidch * [10] clears Latched scpad_parity (both ports) 843255736Sdavidch */ 844255736Sdavidch REG_WR(sc, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x780); 845255736Sdavidch} 846255736Sdavidch 847255736Sdavidchstatic inline void ecore_enable_blocks_parity(struct bxe_softc *sc) 848255736Sdavidch{ 849255736Sdavidch int i; 850255736Sdavidch 851255736Sdavidch for (i = 0; i < ARRSIZE(ecore_blocks_parity_data); i++) { 852255736Sdavidch uint32_t reg_mask = ecore_parity_reg_mask(sc, i); 853255736Sdavidch 854255736Sdavidch if (reg_mask) 855255736Sdavidch REG_WR(sc, ecore_blocks_parity_data[i].mask_addr, 856255736Sdavidch ecore_blocks_parity_data[i].en_mask & reg_mask); 857255736Sdavidch } 858255736Sdavidch 859255736Sdavidch /* Enable MCP parity attentions */ 860255736Sdavidch ecore_set_mcp_parity(sc, TRUE); 861255736Sdavidch} 862255736Sdavidch 863255736Sdavidch 864255736Sdavidch#endif /* ECORE_INIT_H */ 865255736Sdavidch 866